/********************************************************************* * 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 #include #include #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 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