Commit daa21f1d authored by David Partyka's avatar David Partyka
Browse files

ENH: First pass at adding c++ wrapper api for NetCDF.

parent 97a3321d
......@@ -21,6 +21,11 @@ SET(netcdf_SRCS
var.c
)
SET(netcdfcpp_SRCS
netcdf.cpp
ncvalues.cpp
)
IF(APPLE)
SET_SOURCE_FILES_PROPERTIES(
v2i.c
......@@ -75,7 +80,7 @@ ENDMACRO(CHECK_TYPE_SIZE_EX)
MACRO(C_SOURCE_COMPILES SOURCE VAR)
IF("${VAR}" MATCHES "^${VAR}$")
SET(MACRO_CHECK_FUNCTION_DEFINITIONS
SET(MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
IF(CMAKE_REQUIRED_LIBRARIES)
SET(C_SOURCE_COMPILES_ADD_LIBRARIES
......@@ -88,20 +93,20 @@ MACRO(C_SOURCE_COMPILES SOURCE VAR)
TRY_COMPILE(${VAR}
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}/CMakeTmp/src.c
CMAKE_FLAGS
CMAKE_FLAGS
"${C_SOURCE_COMPILES_ADD_LIBRARIES}"
OUTPUT_VARIABLE OUTPUT)
IF(${VAR})
SET(${VAR} 1 CACHE INTERNAL "NetCDF test ${FUNCTION}")
MESSAGE(STATUS "Performing NetCDF Test ${VAR} - Success")
WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log
WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeOutput.log
"Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SOURCE}\n" APPEND)
ELSE(${VAR})
MESSAGE(STATUS "Performing NetCDF Test ${VAR} - Failed")
SET(${VAR} "" CACHE INTERNAL "NetCDF test ${FUNCTION}")
WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log
WRITE_FILE(${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log
"Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SOURCE}\n" APPEND)
......@@ -110,7 +115,7 @@ MACRO(C_SOURCE_COMPILES SOURCE VAR)
ENDMACRO(C_SOURCE_COMPILES)
CHECK_INCLUDE_FILES("stdlib.h;stdarg.h;string.h;float.h" STDC_HEADERS)
FOREACH(file
FOREACH(file
"alloca.h"
"stdlib.h"
"sys/types.h"
......@@ -162,7 +167,7 @@ IF(HAVE_SYS_STAT_H)
C_SOURCE_COMPILES("${testsrc}" HAVE_ST_BLKSIZE)
ENDIF(HAVE_SYS_STAT_H)
#
#
SET(testsrc
"main()
{
......@@ -258,6 +263,8 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ncconfig.h.in
ADD_LIBRARY(vtkNetCDF
${netcdf_SRCS})
ADD_LIBRARY(vtkNetCDF_c++ ${netcdfcpp_SRCS})
# Take care of symbol export/import on Windows
ADD_DEFINITIONS("-DNC_DLL_EXPORT")
......
/*********************************************************************
* Copyright 1992, University Corporation for Atmospheric Research
* See netcdf/README file for copying and redistribution conditions.
*
* Purpose: implementation of classes of typed arrays for netCDF
*
* $Header: /upc/share/CVS/netcdf-3/cxx/ncvalues.cpp,v 1.12 2008/03/05 16:45:32 russ Exp $
*********************************************************************/
#include <ncconfig.h>
#include <iostream>
#include <string>
#include <cstring>
#include "ncvalues.h"
NcValues::NcValues( void ) : the_type(ncNoType), the_number(0)
{}
NcValues::NcValues(NcType type, long num)
: the_type(type), the_number(num)
{}
NcValues::~NcValues( void )
{}
long NcValues::num( void )
{
return the_number;
}
std::ostream& operator<< (std::ostream& os, const NcValues& vals)
{
return vals.print(os);
}
implement(NcValues,ncbyte)
implement(NcValues,char)
implement(NcValues,short)
implement(NcValues,int)
implement(NcValues,nclong)
implement(NcValues,long)
implement(NcValues,float)
implement(NcValues,double)
Ncbytes_for_one_implement(ncbyte)
Ncbytes_for_one_implement(char)
Ncbytes_for_one_implement(short)
Ncbytes_for_one_implement(int)
Ncbytes_for_one_implement(nclong)
Ncbytes_for_one_implement(long)
Ncbytes_for_one_implement(float)
Ncbytes_for_one_implement(double)
as_ncbyte_implement(short)
as_ncbyte_implement(int)
as_ncbyte_implement(nclong)
as_ncbyte_implement(long)
as_ncbyte_implement(float)
as_ncbyte_implement(double)
inline ncbyte NcValues_char::as_ncbyte( long n ) const
{
return the_values[n];
}
inline ncbyte NcValues_ncbyte::as_ncbyte( long n ) const
{
return the_values[n];
}
as_char_implement(short)
as_char_implement(int)
as_char_implement(nclong)
as_char_implement(long)
as_char_implement(float)
as_char_implement(double)
inline char NcValues_ncbyte::as_char( long n ) const
{
return the_values[n] > CHAR_MAX ? ncBad_char : (char) the_values[n];
}
inline char NcValues_char::as_char( long n ) const
{
return the_values[n];
}
as_short_implement(int)
as_short_implement(nclong)
as_short_implement(long)
as_short_implement(float)
as_short_implement(double)
inline short NcValues_ncbyte::as_short( long n ) const
{
return the_values[n];
}
inline short NcValues_char::as_short( long n ) const
{
return the_values[n];
}
inline short NcValues_short::as_short( long n ) const
{
return the_values[n];
}
as_int_implement(float)
as_int_implement(double)
inline int NcValues_ncbyte::as_int( long n ) const
{
return the_values[n];
}
inline int NcValues_char::as_int( long n ) const
{
return the_values[n];
}
inline int NcValues_short::as_int( long n ) const
{
return the_values[n];
}
inline int NcValues_int::as_int( long n ) const
{
return the_values[n];
}
inline int NcValues_nclong::as_int( long n ) const
{
return the_values[n];
}
inline int NcValues_long::as_int( long n ) const
{
return the_values[n];
}
as_nclong_implement(float)
as_nclong_implement(double)
inline nclong NcValues_ncbyte::as_nclong( long n ) const
{
return the_values[n];
}
inline nclong NcValues_char::as_nclong( long n ) const
{
return the_values[n];
}
inline nclong NcValues_short::as_nclong( long n ) const
{
return the_values[n];
}
inline nclong NcValues_int::as_nclong( long n ) const
{
return the_values[n];
}
inline nclong NcValues_nclong::as_nclong( long n ) const
{
return the_values[n];
}
inline nclong NcValues_long::as_nclong( long n ) const
{
return the_values[n];
}
as_long_implement(float)
as_long_implement(double)
inline long NcValues_ncbyte::as_long( long n ) const
{
return the_values[n];
}
inline long NcValues_char::as_long( long n ) const
{
return the_values[n];
}
inline long NcValues_short::as_long( long n ) const
{
return the_values[n];
}
inline long NcValues_int::as_long( long n ) const
{
return the_values[n];
}
inline long NcValues_nclong::as_long( long n ) const
{
return the_values[n];
}
inline long NcValues_long::as_long( long n ) const
{
return the_values[n];
}
as_float_implement(ncbyte)
as_float_implement(char)
as_float_implement(short)
as_float_implement(int)
as_float_implement(nclong)
as_float_implement(long)
as_float_implement(float)
as_float_implement(double)
as_double_implement(ncbyte)
as_double_implement(char)
as_double_implement(short)
as_double_implement(int)
as_double_implement(nclong)
as_double_implement(long)
as_double_implement(float)
as_double_implement(double)
as_string_implement(short)
as_string_implement(int)
as_string_implement(nclong)
as_string_implement(long)
as_string_implement(float)
as_string_implement(double)
inline char* NcValues_ncbyte::as_string( long n ) const
{
char* s = new char[the_number + 1];
s[the_number] = '\0';
strncpy(s, (const char*)the_values + n, (int)the_number);
return s;
}
inline char* NcValues_char::as_string( long n ) const
{
char* s = new char[the_number + 1];
s[the_number] = '\0';
strncpy(s, (const char*)the_values + n, (int)the_number);
return s;
}
std::ostream& NcValues_short::print(std::ostream& os) const
{
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
return os;
}
std::ostream& NcValues_int::print(std::ostream& os) const
{
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
return os;
}
std::ostream& NcValues_nclong::print(std::ostream& os) const
{
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
return os;
}
std::ostream& NcValues_long::print(std::ostream& os) const
{
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
return os;
}
std::ostream& NcValues_ncbyte::print(std::ostream& os) const
{
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
return os;
}
std::ostream& NcValues_char::print(std::ostream& os) const
{
os << '"';
long len = the_number;
while (the_values[--len] == '\0') // don't output trailing null bytes
;
for(int i = 0; i <= len; i++)
os << the_values[i] ;
os << '"';
return os;
}
std::ostream& NcValues_float::print(std::ostream& os) const
{
std::streamsize save=os.precision();
os.precision(7);
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1] ;
os.precision(save);
return os;
}
std::ostream& NcValues_double::print(std::ostream& os) const
{
std::streamsize save=os.precision();
os.precision(15);
for(int i = 0; i < the_number - 1; i++)
os << the_values[i] << ", ";
if (the_number > 0)
os << the_values[the_number-1];
os.precision(save);
return os;
}
/*********************************************************************
* 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) \