[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[netCDF #XLE-835004]: Spoke to soon [netCDF #DZZ-360644



Mike,

I've attached the netcdfcpp.h and the ncvalues.h file it also requires.

I don't think we have a Windows .lib or .dll with the C++ interface built,
but I've Cc:ed Ed in case he knows of one.

--Russ

Russ Rew                                         UCAR Unidata Program
address@hidden                     http://www.unidata.ucar.edu



Ticket Details
===================
Ticket ID: XLE-835004
Department: Support netCDF
Priority: Normal
Status: Closed
/*********************************************************************
 *   Copyright 1992, University Corporation for Atmospheric Research
 *   See netcdf/README file for copying and redistribution conditions.
 *
 *   Purpose:   interface for classes of typed arrays for netCDF
 *
 *   $Header: /upc/share/CVS/netcdf-3/cxx/ncvalues.h,v 1.7 2006/07/26 21:12:06 
russ Exp $
 *********************************************************************/

#ifndef Ncvalues_def
#define Ncvalues_def

#include <iostream>
#include <sstream>
#include <limits.h>
#include "netcdf.h"

// Documentation warned this might change and now it has, for
// consistency with C interface 
typedef signed char ncbyte;

#define NC_UNSPECIFIED ((nc_type)0)

// C++ interface dates from before netcdf-3, still uses some netcdf-2 names
#ifdef NO_NETCDF_2
#define NC_LONG NC_INT
#define FILL_LONG NC_FILL_INT
typedef int nclong;
#define NC_FATAL        1
#define NC_VERBOSE      2
#endif

enum NcType 
{
  ncNoType = NC_UNSPECIFIED, 
  ncByte = NC_BYTE, 
  ncChar = NC_CHAR, 
  ncShort = NC_SHORT, 
  ncInt = NC_INT,
  ncLong = NC_LONG,             // deprecated, someday want to use for 64-bit 
ints
  ncFloat = NC_FLOAT, 
  ncDouble = NC_DOUBLE
};

#define ncBad_ncbyte ncBad_byte
static const ncbyte ncBad_byte = NC_FILL_BYTE;
static const char ncBad_char = NC_FILL_CHAR;
static const short ncBad_short = NC_FILL_SHORT;
static const nclong ncBad_nclong = FILL_LONG; // deprecated
static const int ncBad_int = NC_FILL_INT;
static const long ncBad_long = FILL_LONG; // deprecated
static const float ncBad_float = NC_FILL_FLOAT;
static const double ncBad_double = NC_FILL_DOUBLE;

// macros to glue tokens together to form new names (used to be in generic.h)
#define name2(a,b) a ## b
#define declare(clas,t)        name2(clas,declare)(t)
#define implement(clas,t)      name2(clas,implement)(t)
// This is the same as the name2 macro, but we need to define our own
// version since rescanning something generated with the name2 macro
// won't necessarily cause name2 to be expanded again.
#define makename2(z, y)         makename2_x(z, y)
#define makename2_x(z, y)               z##y

#define NcVal(TYPE) makename2(NcValues_,TYPE)

#define NcValuesdeclare(TYPE)                                                 \
class NcVal(TYPE) : public NcValues                                           \
{                                                                             \
  public:                                                                     \
    NcVal(TYPE)( void );                                                      \
    NcVal(TYPE)(long num);                                                    \
    NcVal(TYPE)(long num, const TYPE* vals);                                  \
    NcVal(TYPE)(const NcVal(TYPE)&);                                          \
    virtual NcVal(TYPE)& operator=(const NcVal(TYPE)&);                       \
    virtual ~NcVal(TYPE)( void );                                             \
    virtual void* base( void ) const;                                         \
    virtual int bytes_for_one( void ) const;                                  \
    virtual ncbyte as_ncbyte( long n ) const;                                 \
    virtual char as_char( long n ) const;                                     \
    virtual short as_short( long n ) const;                                   \
    virtual int as_int( long n ) const;                                       \
    virtual int as_nclong( long n ) const;                                    \
    virtual long as_long( long n ) const;                                     \
    virtual float as_float( long n ) const;                                   \
    virtual double as_double( long n ) const;                                 \
    virtual char* as_string( long n ) const;                                  \
    virtual int invalid( void ) const;                                        \
  private:                                                                    \
    TYPE* the_values;                                                         \
    std::ostream& print(std::ostream&) const;                                 \
};

#define NcTypeEnum(TYPE) makename2(_nc__,TYPE)
#define _nc__ncbyte ncByte
#define _nc__char ncChar
#define _nc__short ncShort
#define _nc__int ncInt
#define _nc__nclong ncLong
#define _nc__long ncLong
#define _nc__float ncFloat
#define _nc__double ncDouble
#define NcValuesimplement(TYPE)                                               \
NcVal(TYPE)::NcVal(TYPE)( void )                                              \
        : NcValues(NcTypeEnum(TYPE), 0), the_values(0)                        \
{}                                                                            \
                                                                              \
NcVal(TYPE)::NcVal(TYPE)(long num, const TYPE* vals)                          \
        : NcValues(NcTypeEnum(TYPE), num)                                     \
{                                                                             \
    the_values = new TYPE[num];                                               \
    for(int i = 0; i < num; i++)                                              \
      the_values[i] = vals[i];                                                \
}                                                                             \
                                                                              \
NcVal(TYPE)::NcVal(TYPE)(long num)                                            \
        : NcValues(NcTypeEnum(TYPE), num), the_values(new TYPE[num])          \
{}                                                                            \
                                                                              \
NcVal(TYPE)::NcVal(TYPE)(const NcVal(TYPE)& v) :                              \
    NcValues(v)                                                               \
{                                                                             \
    delete[] the_values;                                                      \
    the_values = new TYPE[v.the_number];                                      \
    for(int i = 0; i < v.the_number; i++)                                     \
      the_values[i] = v.the_values[i];                                        \
}                                                                             \
                                                                              \
NcVal(TYPE)& NcVal(TYPE)::operator=(const NcVal(TYPE)& v)                     \
{                                                                             \
    if ( &v != this) {                                                        \
      NcValues::operator=(v);                                                 \
      delete[] the_values;                                                    \
      the_values = new TYPE[v.the_number];                                    \
      for(int i = 0; i < v.the_number; i++)                                   \
        the_values[i] = v.the_values[i];                                      \
    }                                                                         \
    return *this;                                                             \
}                                                                             \
                                                                              \
void* NcVal(TYPE)::base( void ) const                                         \
{                                                                             \
    return the_values;                                                        \
}                                                                             \
                                                                              \
NcVal(TYPE)::~NcVal(TYPE)( void )                                             \
{                                                                             \
    delete[] the_values;                                                      \
}                                                                             \
                                                                              \
int NcVal(TYPE)::invalid( void ) const                                        \
{                                                                             \
    for(int i=0;i<the_number;i++)                                             \
        if (the_values[i] == makename2(ncBad_,TYPE)) return 1;                \
    return 0;                                                                 \
}                                                                             \


#define Ncbytes_for_one_implement(TYPE)                                       \
int NcVal(TYPE)::bytes_for_one( void ) const                                  \
{                                                                             \
    return sizeof(TYPE);                                                      \
}

#define as_ncbyte_implement(TYPE)                                             \
ncbyte NcVal(TYPE)::as_ncbyte( long n ) const                                 \
{                                                                             \
    if (the_values[n] < 0 || the_values[n] > UCHAR_MAX)                       \
      return ncBad_byte;                                                      \
    return (ncbyte) the_values[n];                                            \
}

#define as_char_implement(TYPE)                                               \
char NcVal(TYPE)::as_char( long n ) const                                     \
{                                                                             \
    if (the_values[n] < CHAR_MIN || the_values[n] > CHAR_MAX)                 \
      return ncBad_char;                                                      \
    return (char) the_values[n];                                              \
}

#define as_short_implement(TYPE)                                              \
short NcVal(TYPE)::as_short( long n ) const                                   \
{                                                                             \
    if (the_values[n] < SHRT_MIN || the_values[n] > SHRT_MAX)                 \
      return ncBad_short;                                                     \
    return (short) the_values[n];                                             \
}

#define NCINT_MIN INT_MIN
#define NCINT_MAX INT_MAX
#define as_int_implement(TYPE)                                        \
int NcVal(TYPE)::as_int( long n ) const                               \
{                                                                             \
    if (the_values[n] < NCINT_MIN || the_values[n] > NCINT_MAX)       \
      return ncBad_int;                                               \
    return (int) the_values[n];                                       \
}

#define NCLONG_MIN INT_MIN
#define NCLONG_MAX INT_MAX
#define as_nclong_implement(TYPE)                                             \
nclong NcVal(TYPE)::as_nclong( long n ) const                                 \
{                                                                             \
    if (the_values[n] < NCLONG_MIN || the_values[n] > NCLONG_MAX)             \
      return ncBad_nclong;                                                    \
    return (nclong) the_values[n];                                            \
}

#define as_long_implement(TYPE)                                               \
long NcVal(TYPE)::as_long( long n ) const                                     \
{                                                                             \
    if (the_values[n] < LONG_MIN || the_values[n] > LONG_MAX)                 \
      return ncBad_long;                                                      \
    return (long) the_values[n];                                              \
}

#define as_float_implement(TYPE)                                              \
inline float NcVal(TYPE)::as_float( long n ) const                            \
{                                                                             \
    return (float) the_values[n];                                             \
}

#define as_double_implement(TYPE)                                             \
inline double NcVal(TYPE)::as_double( long n ) const                          \
{                                                                             \
    return (double) the_values[n];                                            \
}

#define as_string_implement(TYPE)                                             \
char* NcVal(TYPE)::as_string( long n ) const                                  \
{                                                                             \
    char* s = new char[32];                                                   \
    std::ostringstream ostr;                                                  \
    ostr << the_values[n];                                            \
    ostr.str().copy(s, std::string::npos);                                      
         \
    s[ostr.str().length()] = 0;                                                 
    \
    return s;                                                                 \
}

class NcValues                  // ABC for value blocks
{
  public:
    NcValues( void );
    NcValues(NcType, long);
    virtual ~NcValues( void );
    virtual long num( void );
    virtual std::ostream& print(std::ostream&) const = 0;
    virtual void* base( void ) const = 0;
    virtual int bytes_for_one( void ) const = 0;

    // The following member functions provide conversions from the value
    // type to a desired basic type.  If the value is out of range, the
    // default "fill-value" for the appropriate type is returned.
    virtual ncbyte as_ncbyte( long n ) const = 0; // nth value as a byte
    virtual char as_char( long n ) const = 0;     // nth value as char
    virtual short as_short( long n ) const = 0;   // nth value as short
    virtual int    as_int( long n ) const = 0;    // nth value as int
    virtual int    as_nclong( long n ) const = 0; // nth value as nclong
    virtual long as_long( long n ) const = 0;     // nth value as long
    virtual float as_float( long n ) const = 0;   // nth value as floating-point
    virtual double as_double( long n ) const = 0; // nth value as double
    virtual char* as_string( long n ) const = 0;  // value as string
    
  protected:
    NcType the_type;
    long the_number;
    friend std::ostream& operator<< (std::ostream&, const NcValues&);
};

declare(NcValues,ncbyte)
declare(NcValues,char)
declare(NcValues,short)
declare(NcValues,int)
declare(NcValues,nclong)
declare(NcValues,long)
declare(NcValues,float)
declare(NcValues,double)

#endif
/*********************************************************************
 *   Copyright 1992, University Corporation for Atmospheric Research
 *   See netcdf/README file for copying and redistribution conditions.
 *
 *   Purpose:   C++ class interface for netCDF
 *
 *   $Header: /upc/share/CVS/netcdf-3/cxx/netcdfcpp.h,v 1.14 2006/07/31 
20:42:48 russ Exp $
 *********************************************************************/

#ifndef NETCDF_HH
#define NETCDF_HH

#include "ncvalues.h"          // arrays that know their element type

typedef const char* NcToken;    // names for netCDF objects
typedef unsigned int NcBool;    // many members return 0 on failure

class NcDim;                    // dimensions
class NcVar;                    // variables
class NcAtt;                    // attributes

/*
 * ***********************************************************************
 * A netCDF file.
 * ***********************************************************************
 */
class NcFile
{
  public:

    virtual ~NcFile( void );

    enum FileMode {
        ReadOnly,       // file exists, open read-only
        Write,          // file exists, open for writing
        Replace,        // create new file, even if already exists
        New             // create new file, fail if already exists
      };

    enum FileFormat {
       Classic,         // netCDF classic format (i.e. version 1 format)
       Offset64Bits,    // netCDF 64-bit offset format
       Netcdf4,         // netCDF-4 using HDF5 format
       Netcdf4Classic,  // netCDF-4 using HDF5 format using only netCDF-3 calls
       BadFormat
    };

    NcFile( const char * path, FileMode = ReadOnly ,
            size_t *chunksizeptr = NULL, // optional tuning parameters
            size_t initialsize = 0,
            FileFormat = Classic );

    NcBool is_valid( void ) const;         // opened OK in ctr, still valid

    int num_dims( void ) const;            // number of dimensions
    int num_vars( void ) const;            // number of variables
    int num_atts( void ) const;            // number of (global) attributes

    NcDim* get_dim( NcToken ) const;       // dimension by name
    NcVar* get_var( NcToken ) const;       // variable by name
    NcAtt* get_att( NcToken ) const;       // global attribute by name

    NcDim* get_dim( int ) const;           // n-th dimension
    NcVar* get_var( int ) const;           // n-th variable
    NcAtt* get_att( int ) const;           // n-th global attribute
    NcDim* rec_dim( void ) const;          // unlimited dimension, if any
    
    // Add new dimensions, variables, global attributes.
    // These put the file in "define" mode, so could be expensive.
    virtual NcDim* add_dim( NcToken dimname, long dimsize );
    virtual NcDim* add_dim( NcToken dimname );     // unlimited

    virtual NcVar* add_var( NcToken varname, NcType type,       // scalar
                    const NcDim* dim0=0,                // 1-dim
                    const NcDim* dim1=0,                // 2-dim
                    const NcDim* dim2=0,                // 3-dim
                    const NcDim* dim3=0,                // 4-dim
                    const NcDim* dim4=0 );              // 5-dim
    virtual NcVar* add_var( NcToken varname, NcType type,       // n-dim
                          int ndims, const NcDim** dims );

    NcBool add_att( NcToken attname, char );             // scalar attributes
    NcBool add_att( NcToken attname, ncbyte );
    NcBool add_att( NcToken attname, short );
    NcBool add_att( NcToken attname, long );
    NcBool add_att( NcToken attname, int );
    NcBool add_att( NcToken attname, float );
    NcBool add_att( NcToken attname, double );
    NcBool add_att( NcToken attname, const char*);       // string attribute
    NcBool add_att( NcToken attname, int, const char* ); // vector attributes
    NcBool add_att( NcToken attname, int, const ncbyte* );
    NcBool add_att( NcToken attname, int, const short* );
    NcBool add_att( NcToken attname, int, const long* );
    NcBool add_att( NcToken attname, int, const int* );
    NcBool add_att( NcToken attname, int, const float* );
    NcBool add_att( NcToken attname, int, const double* );

    enum FillMode {
        Fill = NC_FILL,                    // prefill (default)
        NoFill = NC_NOFILL,                // don't prefill
        Bad
      };

    NcBool set_fill( FillMode = Fill );    // set fill-mode
    FillMode get_fill( void ) const;       // get fill-mode
    FileFormat get_format( void ) const;   // get format version

    NcBool sync( void );                   // synchronize to disk
    NcBool close( void );                  // to close earlier than dtr
    NcBool abort( void );                  // back out of bad defines
    
    // Needed by other Nc classes, but users will not need them
    NcBool define_mode( void ); // leaves in define mode, if possible
    NcBool data_mode( void );   // leaves in data mode, if possible
    int id( void ) const;       // id used by C interface

  protected:
    int the_id;
    int in_define_mode;
    FillMode the_fill_mode;
    NcDim** dimensions;
    NcVar** variables;
    NcVar* globalv;             // "variable" for global attributes
};

/*
 * For backward compatibility.  We used to derive NcOldFile and NcNewFile
 * from NcFile, but that was over-zealous inheritance.
 */
#define NcOldFile NcFile
#define NcNewFile NcFile
#define Clobber Replace
#define NoClobber New

/*
 * **********************************************************************
 * A netCDF dimension, with a name and a size.  These are only created
 * by NcFile member functions, because they cannot exist independently
 * of an open netCDF file.
 * **********************************************************************
 */
class NcDim
{
  public:
    NcToken name( void ) const;
    long size( void ) const;
    NcBool is_valid( void ) const;
    NcBool is_unlimited( void ) const;
    NcBool rename( NcToken newname );
    int id( void ) const;
    NcBool sync( void );

  private:
    NcFile *the_file;           // not const because of rename
    int the_id;
    char *the_name;

    NcDim(NcFile*, int num);    // existing dimension
    NcDim(NcFile*, NcToken name, long sz); // defines a new dim
    virtual ~NcDim( void );
    
    // to construct dimensions, since constructor is private
    friend class NcFile;
};


/*
 * **********************************************************************
 * Abstract base class for a netCDF variable or attribute, both of which
 * have a name, a type, and associated values.  These only exist as
 * components of an open netCDF file.
 * **********************************************************************
 */
class NcTypedComponent
{
  public:
    virtual ~NcTypedComponent( void ) {}
    virtual NcToken name( void ) const = 0;
    virtual NcType type( void ) const = 0;
    virtual NcBool is_valid( void ) const = 0;
    virtual long num_vals( void ) const = 0; 
    virtual NcBool rename( NcToken newname ) = 0;
    virtual NcValues* values( void ) const = 0; // block of all values

    // The following member functions provide conversions from the value
    // type to a desired basic type.  If the value is out of range,
    // the default "fill-value" for the appropriate type is returned.

    virtual ncbyte as_ncbyte( long n ) const;    // nth value as an unsgnd char
    virtual char as_char( long n ) const;        // nth value as char
    virtual short as_short( long n ) const;      // nth value as short
    virtual int as_int( long n ) const;          // nth value as int
    virtual int as_nclong( long n ) const;       // nth value as nclong 
(deprecated)
    virtual long as_long( long n ) const;        // nth value as long
    virtual float as_float( long n ) const;      // nth value as floating-point
    virtual double as_double( long n ) const;    // nth value as double
    virtual char* as_string( long n ) const;     // nth value as string

  protected:
    NcFile *the_file;
    NcTypedComponent( NcFile* );
    virtual NcValues* get_space( long numVals = 0 ) const;  // to hold values
};


/*
 * **********************************************************************
 * netCDF variables.  In addition to a name and a type, these also have
 * a shape, given by a list of dimensions
 * **********************************************************************
 */
class NcVar : public NcTypedComponent
{
  public:
    virtual ~NcVar( void );
    NcToken name( void ) const;
    NcType type( void ) const;
    NcBool is_valid( void ) const;
    int num_dims( void ) const;         // dimensionality of variable
    NcDim* get_dim( int ) const;        // n-th dimension
    long* edges( void ) const;          // dimension sizes
    int num_atts( void ) const;         // number of attributes
    NcAtt* get_att( NcToken ) const;    // attribute by name
    NcAtt* get_att( int ) const;        // n-th attribute
    long num_vals( void ) const;        // product of dimension sizes
    NcValues* values( void ) const;     // all values
    
    // Put scalar or 1, ..., 5 dimensional arrays by providing enough
    // arguments.  Arguments are edge lengths, and their number must not
    // exceed variable's dimensionality.  Start corner is [0,0,..., 0] by
    // default, but may be reset using the set_cur() member.  FALSE is
    // returned if type of values does not match type for variable.
    NcBool put( const ncbyte* vals,
                long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
    NcBool put( const char* vals,
                long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
    NcBool put( const short* vals,
                long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
    NcBool put( const int* vals,
                long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
    NcBool put( const long* vals,
                long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
    NcBool put( const float* vals,
                long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );
    NcBool put( const double* vals,
                long c0=0, long c1=0, long c2=0, long c3=0, long c4=0 );

    // Put n-dimensional arrays, starting at [0, 0, ..., 0] by default,
    // may be reset with set_cur().
    NcBool put( const ncbyte* vals, const long* counts );
    NcBool put( const char* vals, const long* counts );
    NcBool put( const short* vals, const long* counts );
    NcBool put( const int* vals, const long* counts );
    NcBool put( const long* vals, const long* counts );
    NcBool put( const float* vals, const long* counts );
    NcBool put( const double* vals, const long* counts );

    // Get scalar or 1, ..., 5 dimensional arrays by providing enough
    // arguments.  Arguments are edge lengths, and their number must not
    // exceed variable's dimensionality.  Start corner is [0,0,..., 0] by
    // default, but may be reset using the set_cur() member.
    NcBool get( ncbyte* vals, long c0=0, long c1=0,
                long c2=0, long c3=0, long c4=0 ) const;
    NcBool get( char* vals, long c0=0, long c1=0,
                long c2=0, long c3=0, long c4=0 ) const;
    NcBool get( short* vals, long c0=0, long c1=0,
                long c2=0, long c3=0, long c4=0 ) const;
    NcBool get( int* vals, long c0=0, long c1=0,
                long c2=0, long c3=0, long c4=0 ) const;
    NcBool get( long* vals, long c0=0, long c1=0,
                long c2=0, long c3=0, long c4=0 ) const;
    NcBool get( float* vals, long c0=0, long c1=0,
                long c2=0, long c3=0, long c4=0 ) const;
    NcBool get( double* vals, long c0=0, long c1=0,
                long c2=0, long c3=0, long c4=0 ) const; 

    // Get n-dimensional arrays, starting at [0, 0, ..., 0] by default,
    // may be reset with set_cur().
    NcBool get( ncbyte* vals, const long* counts ) const;
    NcBool get( char* vals, const long* counts ) const;
    NcBool get( short* vals, const long* counts ) const;
    NcBool get( int* vals, const long* counts ) const;
    NcBool get( long* vals, const long* counts ) const;
    NcBool get( float* vals, const long* counts ) const;
    NcBool get( double* vals, const long* counts ) const;

    NcBool set_cur(long c0=-1, long c1=-1, long c2=-1,
                         long c3=-1, long c4=-1);
    NcBool set_cur(long* cur);

    // these put file in define mode, so could be expensive
    NcBool add_att( NcToken, char );             // add scalar attributes
    NcBool add_att( NcToken, ncbyte );
    NcBool add_att( NcToken, short );
    NcBool add_att( NcToken, int );
    NcBool add_att( NcToken, long );
    NcBool add_att( NcToken, float );
    NcBool add_att( NcToken, double );
    NcBool add_att( NcToken, const char* );      // string attribute
    NcBool add_att( NcToken, int, const char* ); // vector attributes
    NcBool add_att( NcToken, int, const ncbyte* );
    NcBool add_att( NcToken, int, const short* );
    NcBool add_att( NcToken, int, const int* );
    NcBool add_att( NcToken, int, const long* );
    NcBool add_att( NcToken, int, const float* );
    NcBool add_att( NcToken, int, const double* );

    NcBool rename( NcToken newname );

    long rec_size ( void );             // number of values per record
    long rec_size ( NcDim* );           // number of values per dimension slice

    // Though following are intended for record variables, they also work
    // for other variables, using first dimension as record dimension.

    // Get a record's worth of data
    NcValues *get_rec(void);            // get current record
    NcValues *get_rec(long rec);        // get specified record
    NcValues *get_rec(NcDim* d);        // get current dimension slice
    NcValues *get_rec(NcDim* d, long slice); // get specified dimension slice

    // Put a record's worth of data in current record
    NcBool put_rec( const ncbyte* vals );
    NcBool put_rec( const char* vals );
    NcBool put_rec( const short* vals );
    NcBool put_rec( const int* vals );
    NcBool put_rec( const long* vals );
    NcBool put_rec( const float* vals );
    NcBool put_rec( const double* vals );

    // Put a dimension slice worth of data in current dimension slice
    NcBool put_rec( NcDim* d, const ncbyte* vals );
    NcBool put_rec( NcDim* d, const char* vals );
    NcBool put_rec( NcDim* d, const short* vals );
    NcBool put_rec( NcDim* d, const int* vals );
    NcBool put_rec( NcDim* d, const long* vals );
    NcBool put_rec( NcDim* d, const float* vals );
    NcBool put_rec( NcDim* d, const double* vals );

    // Put a record's worth of data in specified record
    NcBool put_rec( const ncbyte* vals, long rec );
    NcBool put_rec( const char* vals, long rec );
    NcBool put_rec( const short* vals, long rec );
    NcBool put_rec( const int* vals, long rec );
    NcBool put_rec( const long* vals, long rec );
    NcBool put_rec( const float* vals, long rec );
    NcBool put_rec( const double* vals, long rec );

    // Put a dimension slice worth of data in specified dimension slice
    NcBool put_rec( NcDim* d, const ncbyte* vals, long slice );
    NcBool put_rec( NcDim* d, const char* vals, long slice );
    NcBool put_rec( NcDim* d, const short* vals, long slice );
    NcBool put_rec( NcDim* d, const int* vals, long slice );
    NcBool put_rec( NcDim* d, const long* vals, long slice );
    NcBool put_rec( NcDim* d, const float* vals, long slice );
    NcBool put_rec( NcDim* d, const double* vals, long slice );

    // Get first record index corresponding to specified key value(s)
    long get_index( const ncbyte* vals );
    long get_index( const char* vals );
    long get_index( const short* vals );
    long get_index( const int* vals );
    long get_index( const long* vals );
    long get_index( const float* vals );
    long get_index( const double* vals );

    // Get first index of specified dimension corresponding to key values
    long get_index( NcDim* d, const ncbyte* vals );
    long get_index( NcDim* d, const char* vals );
    long get_index( NcDim* d, const short* vals );
    long get_index( NcDim* d, const int* vals );
    long get_index( NcDim* d, const long* vals );
    long get_index( NcDim* d, const float* vals );
    long get_index( NcDim* d, const double* vals );

    // Set current record
    void set_rec ( long rec );
    // Set current dimension slice
    void set_rec ( NcDim* d, long slice );

    int id( void ) const;               // rarely needed, C interface id
    NcBool sync( void );
    
  private:
    int dim_to_index(NcDim* rdim);
    int the_id;
    long* the_cur;
    char* the_name;
    long* cur_rec;

    // private constructors because only an NcFile creates these
    NcVar( void );
    NcVar(NcFile*, int);

    int attnum( NcToken attname ) const;
    NcToken attname( int attnum ) const;
    void init_cur( void );

    // to make variables, since constructor is private
  friend class NcFile;
};


/*
 * **********************************************************************
 * netCDF attributes.  In addition to a name and a type, these are each
 * associated with a specific variable, or are global to the file.
 * **********************************************************************
 */
class NcAtt : public NcTypedComponent
{
  public:          
    virtual ~NcAtt( void );
    NcToken name( void ) const;
    NcType type( void ) const;
    NcBool is_valid( void ) const;
    long num_vals( void ) const; 
    NcValues* values( void ) const;
    NcBool rename( NcToken newname );
    NcBool remove( void );

  private:
    const NcVar* the_variable;
    char* the_name;
    // protected constructors because only NcVars and NcFiles create
    // attributes
    NcAtt( NcFile*, const NcVar*, NcToken);
    NcAtt( NcFile*, NcToken); // global attribute
    
    // To make attributes, since constructor is private
  friend class NcFile;
  friend NcAtt* NcVar::get_att( NcToken ) const;
};


/*
 * **********************************************************************
 * To control error handling.  Declaring an NcError object temporarily
 * changes the error-handling behavior until the object is destroyed, at
 * which time the previous error-handling behavior is restored.
 * **********************************************************************
 */
class NcError {
  public:
    enum Behavior {
        silent_nonfatal = 0,
        silent_fatal = 1,
        verbose_nonfatal = 2,
        verbose_fatal = 3   
      };

    // constructor saves previous error state, sets new state
    NcError( Behavior b = verbose_fatal );

    // destructor restores previous error state
    virtual ~NcError( void );

    int get_err( void );                 // returns most recent error number
    const char* get_errmsg( void ) {return nc_strerror(get_err());}
    static int set_err( int err );

  private:
    int the_old_state;
    int the_old_err;
    static int ncopts;
    static int ncerr;
};

#endif                          /* NETCDF_HH */