/*
 * Copyright 1993-1996 University Corporation for Atmospheric Research/Unidata
 * 
 * Portions of this software were developed by the Unidata Program at the 
 * University Corporation for Atmospheric Research.
 * 
 * Access and use of this software shall impose the following obligations
 * and understandings on the user. The user is granted the right, without
 * any fee or cost, to use, copy, modify, alter, enhance and distribute
 * this software, and any derivative works thereof, and its supporting
 * documentation for any purpose whatsoever, provided that this entire
 * notice appears in all copies of the software, derivative works and
 * supporting documentation.  Further, UCAR requests that the user credit
 * UCAR/Unidata in any publications that result from the use of this
 * software or in any product that includes this software. The names UCAR
 * and/or Unidata, however, may not be used in any advertising or publicity
 * to endorse or promote any products or commercial entity unless specific
 * written permission is obtained from UCAR/Unidata. The user also
 * understands that UCAR/Unidata is not obligated to provide the user with
 * any support, consulting, training or assistance of any kind with regard
 * to the use, operation and performance of this software nor to provide
 * the user with any updates, revisions, new versions or "bug fixes."
 * 
 * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
 */
/* "$Id: netcdf.h,v 2.4 1996/04/12 16:51:15 russ Exp $" */

#ifndef _NETCDF_
#define _NETCDF_

/*
 * The definitions ncvoid, USE_ENUM, and MAX_NC_OPEN, may need to be set
 * properly for your installation.
 */

/*
 * Argument type in user functions (deprecated, backward compatibility)
 */
#ifndef UD_NO_VOID
#define ncvoid    void
#else
/* system doesn't have void type */
#define ncvoid    char
#endif


/*
 *   If xdr_enum works properly on your system, you can define 
 * USE_ENUM so that nc_type is an enum. 
 * Otherwise, delete this definition so that the nc_type is
 * an int and the valid values are #defined.
 */
#define USE_ENUM


/*
 * The following macro is provided for backward compatibility only.  If you
 * are a new user of netCDF, then you may safely ignore it.  If, however,
 * you have an existing archive of netCDF files that use default
 * floating-point fill values, then you should know that the definition of
 * the default floating-point fill values changed with version 2.3 of the
 * netCDF package.  Prior to this release, the default floating-point fill
 * values were not very portable:  their correct behavior depended not only
 * upon the particular platform, but also upon the compilation
 * environment.  This led to the definition of new, default floating-point
 * fill values that are portable across all platforms and compilation
 * environments.  If you wish, however, to obtain the old, non-portable
 * floating-point fill values, then the following macro should have a true
 * value PRIOR TO BUILDING THE netCDF LIBRARY.
 *
 * Implementation details are contained in the section below on fill values.
 */
#if !defined(NC_OLD_FILLVALUES)
#define NC_OLD_FILLVALUES	0
#endif

/*
 * 	Default fill values, used unless _FillValue attribute is set.
 * These values are stuffed into newly allocated space as appropriate.
 * The hope is that one might use these to notice that a particular datum
 * has not been set.
 */

#define FILL_BYTE	((char)-127)
#define FILL_CHAR	((char)0)
#define FILL_SHORT	((short)-32767)
#define FILL_LONG	((nclong)-2147483647)

#if !NC_OLD_FILLVALUES

#   define FILL_FLOAT	9.9692099683868690e+36 /* near 15 * 2^119 */
#   define FILL_DOUBLE	9.9692099683868690e+36

#else	/* NC_OLD_FILLVALUES below */

/*
 * This section is provided for backward compatibility only.  Using
 * XDR infinities for floating-point fill values has caused more problems
 * than it has solved.  We encourage you to define your own data-specific
 * fill values rather than use default ones (see `_FillValue' below).
 * If, however, you *must* use default fill values, then you should use
 * the above fill values rather than the ones in this section.
 */

/*
 * XDR_F_INFINITY is a float value whose EXTERNAL (xdr)
 * represention is ieee floating infinity.
 * XDR_D_INFINITY is a double value whose EXTERNAL (xdr)
 * represention is ieee double floating point infinity.
 * These are used as default fill values below.
 *
 * This section shows three techniques for setting these:
 *  Direct assignment (vax, cray) - works for non IEEE machines
 *		Doesn't work when IEEE machines don't allow
 *      float or double constants whose values are infinity.
 *  Use of a union (preferred portable method) - should work on
 *      any ANSI compiler with IEEE floating point representations,
 *      modulo byte order and sizeof() considerations.
 *  Use of pointer puns - may work with many older compilers
 *      which don't allow intialization of unions.
 *      Often doesn't work with compilers which have strict
 *      alignment rules.
 */ 

    /* Direct assignment. All cases should be mutually exclusive */

#ifdef vax
#define	XDR_D_INFINITY	1.7014118346046923e+38
#define	XDR_F_INFINITY	1.70141173e+38
#endif /* vax */

#ifdef cray
#define	XDR_D_INFINITY	1.797693134862313000e+308
#define	XDR_F_INFINITY	XDR_D_INFINITY
#endif /* cray */

#ifdef notdef /* you might want to try these, on an IEEE machine */
#define XDR_D_INFINITY	1.797693134862315900e+308
#define XDR_F_INFINITY	3.40282357e+38
#endif

#ifdef __STDC__
    /* Use of a union, assumes IEEE representation and 1 byte unsigned char */

#ifndef    XDR_D_INFINITY
#define USE_D_UNION
     union xdr_d_union {unsigned char bb[8]; double dd;} ;
     extern union xdr_d_union xdr_d_infs ;  /* instantiated in array.c */
#define XDR_D_INFINITY    (xdr_d_infs.dd)
#endif /* !XDR_D_INFINITY */

#ifndef    XDR_F_INFINITY
#define USE_F_UNION
     union xdr_f_union {unsigned char bb[4]; float ff;} ;
     extern union xdr_f_union xdr_f_infs ;  /* instantiated in array.c */
#define  XDR_F_INFINITY    (xdr_f_infs.ff)
#endif /* !XDR_F_INFINITY */


#else /* __STDC__ */
    /* Use of a pointer pun, assumes IEEE representation, 4 byte long */

#ifndef    XDR_D_INFINITY
#define USE_D_LONG_PUN
     extern nclong xdr_d_infinity[] ;  /* instantiated in array.c */
#define XDR_D_INFINITY *(double *)xdr_d_infinity
#endif /* !XDR_D_INFINITY */

#ifndef    XDR_F_INFINITY
#define USE_F_LONG_PUN
     extern nclong xdr_f_infinity ;  /* instantiated in array.c */
#define XDR_F_INFINITY *((float *)&xdr_f_infinity)
#endif /* !XDR_F_INFINITY */

#endif /* __STDC__ */

/* End of INFINITY           section */

#define FILL_FLOAT	XDR_F_INFINITY	/* IEEE Infinity */
#define FILL_DOUBLE	XDR_D_INFINITY

#endif	/* NC_OLD_FILLVALUES above */

/*
 * Added feature. The above values are defaults.
 * If you wish a variable to use a different value than the above
 * defaults, create an attribute with the same type as the variable
 * and the following reserved name. The value you give the attribute
 * will be used as the fill value for that variable.
 */
#define _FillValue	"_FillValue"


/*
 *  masks for the struct NC flags field; passed in as 'mode' arg to
 * nccreate and ncopen.
 *
 */
#define NC_RDWR  1		/* read/write, 0 => readonly */
#define NC_CREAT 2		/* in create phase, cleared by ncendef */
#define NC_EXCL  4		/* on create, don't destroy existing file */
#define NC_INDEF 8		/* in define mode, cleared by ncendef */
#define NC_NSYNC 0x10	/* synchronise numrecs on change */
#define NC_HSYNC 0x20	/* synchronise whole header on change */
#define NC_NDIRTY 0x40	/* numrecs has changed */
#define NC_HDIRTY 0x80  /* header info has changed */
#define NC_NOFILL 0x100	/* Don't fill vars on endef and increase of record */
#define NC_LINK 0x8000	/* isa link */

#define NC_FILL 0	/* argument to ncsetfill to clear NC_NOFILL */

/*
 * 'mode' arguments for nccreate and ncopen
 */
#define NC_NOWRITE   0
#define NC_WRITE     NC_RDWR
#define NC_CLOBBER   (NC_INDEF | NC_CREAT | NC_RDWR)
#define NC_NOCLOBBER (NC_INDEF | NC_EXCL | NC_CREAT | NC_RDWR)

/*
 * 'size' argument to ncdimdef for an unlimited dimension
 */
#define NC_UNLIMITED 0L

/*
 * attribute id to put/get a global attribute
 */
#define NC_GLOBAL -1


/*
 * This can be as large as the maximum number of stdio streams
 * you can have open on your system.
 */
#define MAX_NC_OPEN 32

/*
 * These maximums are enforced by the interface, to facilitate writing
 * applications and utilities.  However, nothing is statically allocated to
 * these sizes internally.
 */
#define MAX_NC_DIMS 100		 /* max dimensions per file */
#define MAX_NC_ATTRS 2000	 /* max global or per variable attributes */
#define MAX_NC_VARS 2000	 /* max variables per file */
#define MAX_NC_NAME 128		 /* max length of a name */
#define MAX_VAR_DIMS MAX_NC_DIMS /* max per variable dimensions */

#ifdef USE_ENUM
/*
 *  The netcdf data types
 */
typedef enum {
	NC_UNSPECIFIED, /* private */
	NC_BYTE,
	NC_CHAR,
	NC_SHORT,
	NC_LONG,
	NC_FLOAT,
	NC_DOUBLE,
	/* private */
	NC_BITFIELD,
	NC_STRING,
	NC_IARRAY,
	NC_DIMENSION,
	NC_VARIABLE,
	NC_ATTRIBUTE
} nc_type ;
#else
typedef int nc_type ;
#define	NC_UNSPECIFIED 0 /* private */
#define	NC_BYTE 1
#define	NC_CHAR 2
#define	NC_SHORT 3
#define	NC_LONG 4
#define	NC_FLOAT 5
#define	NC_DOUBLE 6
	/* private */
#define	NC_BITFIELD 7
#define	NC_STRING 8
#define	NC_IARRAY 9
#define	NC_DIMENSION 10
#define	NC_VARIABLE 11
#define	NC_ATTRIBUTE 12
#endif


/*
 * C data type corresponding to a netCDF NC_LONG argument.
 * This is an `int' on 64-bit computers (e.g. DEC Alpha, IRIX64).
 */
#if defined(NC_NCLONG_T)
    typedef NC_NCLONG_T	nclong;
#else
#   include <limits.h>
#   if defined(INT_MAX) && defined(LONG_MAX) && INT_MAX >= 2147483647
	typedef int	nclong;
#	define  NCLONG_MIN	INT_MIN
#	define  NCLONG_MAX	INT_MAX
#   else
	typedef long	nclong;
#	define  NCLONG_MIN	LONG_MIN
#	define  NCLONG_MAX	LONG_MAX
#   endif
#endif


/*
 * Global netcdf error status variable
 *  Initialized in error.c
 */
#define	NC_NOERR	0	/* No Error */
#define	NC_EBADID	1	/* Not a netcdf id */
#define	NC_ENFILE	2	/* Too many netcdfs open */
#define	NC_EEXIST	3	/* netcdf file exists && NC_NOCLOBBER */
#define	NC_EINVAL	4	/* Invalid Argument */
#define	NC_EPERM	5	/* Write to read only */
#define	NC_ENOTINDEFINE	6	/* Operation not allowed in data mode */
#define	NC_EINDEFINE	7	/* Operation not allowed in define mode */
#define	NC_EINVALCOORDS	8	/* Coordinates out of Domain */
#define	NC_EMAXDIMS	9	/* MAX_NC_DIMS exceeded */
#define	NC_ENAMEINUSE	10	/* String match to name in use */
#define NC_ENOTATT	11	/* Attribute not found */
#define	NC_EMAXATTS	12	/* MAX_NC_ATTRS exceeded */
#define NC_EBADTYPE	13	/* Not a netcdf data type */
#define NC_EBADDIM	14	/* Invalid dimension id */
#define NC_EUNLIMPOS	15	/* NC_UNLIMITED in the wrong index */
#define	NC_EMAXVARS	16	/* MAX_NC_VARS exceeded */
#define NC_ENOTVAR	17	/* Variable not found */
#define NC_EGLOBAL	18	/* Action prohibited on NC_GLOBAL varid */
#define NC_ENOTNC	19	/* Not a netcdf file */
#define NC_ESTS         20      /* In Fortran, string too short */
#define NC_EMAXNAME     21      /* MAX_NC_NAME exceeded */
#define NC_ENTOOL       NC_EMAXNAME   /* Backward compatibility */
#define NC_EUNLIMIT     22      /* NC_UNLIMITED size already in use */

#define	NC_EXDR		32	/* */
#define	NC_SYSERR	-1

extern int ncerr ;

/*
 * Global options variable. Used to determine behavior of error handler.
 *  Initialized in lerror.c
 */
#define	NC_FATAL	1
#define	NC_VERBOSE	2

extern int ncopts ;	/* default is (NC_FATAL | NC_VERBOSE) */

/*
 * NB: The following feature-test line is too long in order to accomodate a 
 * bug in the VMS 5.3 C compiler.
 */
#ifndef HAVE_PROTOTYPES
#   if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) || defined(c_plusplus)
#       define	HAVE_PROTOTYPES
#   endif
#endif

#undef PROTO
#ifdef HAVE_PROTOTYPES 
#   define	PROTO(x)	x
#else
#   define	PROTO(x)	()
#endif

#ifdef __cplusplus
extern "C" {
#endif

extern int nccreate	PROTO((
    const char*	path,
    int		cmode
));
extern int ncopen	PROTO((
    const char*	path,
    int		mode
));
extern int ncredef	PROTO((
    int		ncid
));
extern int ncendef	PROTO((
    int		ncid
));
extern int ncclose	PROTO((
    int		ncid
));
extern int ncinquire	PROTO((
    int		ncid,
    int*	ndims,
    int*	nvars,
    int*	natts, 
    int*	recdim
));
extern int ncsync	PROTO((
    int		ncid
));
extern int ncabort	PROTO((
    int		ncid
));
extern int ncdimdef	PROTO((
    int		ncid,
    const char*	name,
    long	length
));
extern int ncdimid	PROTO((
    int		ncid,
    const char*	name
));
extern int ncdiminq	PROTO((
    int		ncid,
    int		dimid,
    char*	name,
    long*	length
));
extern int ncdimrename	PROTO((
    int		ncid,
    int		dimid,
    const char*	name
));
extern int ncvardef	PROTO((
    int		ncid,
    const char*	name,
    nc_type	datatype, 
    int		ndims,
    const int*	dim
));
extern int ncvarid	PROTO((
    int		ncid,
    const char*	name
));
extern int ncvarinq	PROTO((
    int		ncid,
    int		varid,
    char*	name,
    nc_type*	datatype,
    int*	ndims,
    int*	dim,
    int*	natts
));
extern int ncvarput1	PROTO((
    int		ncid,
    int		varid,
    const long*	coords,
    const void*	value
));
extern int ncvarget1	PROTO((
    int		ncid,
    int		varid,
    const long*	coords,
    void*	value
));
extern int ncvarput	PROTO((
    int		ncid,
    int		varid,
    const long*	start,
    const long*	count, 
    const void*	value
));
extern int ncvarget	PROTO((
    int		ncid,
    int		varid,
    const long*	start,
    const long*	count, 
    void*	value
));
extern int ncvarputs	PROTO((
    int		ncid,
    int		varid,
    const long*	start,
    const long*	count,
    const long*	stride,
    const void*	values
));
extern int ncvargets	PROTO((
    int		ncid,
    int		varid,
    const long*	start,
    const long*	count,
    const long*	stride,
    void*	values
));
extern int ncvarputg	PROTO((
    int		ncid,
    int		varid,
    const long*	start,
    const long*	count,
    const long*	stride,
    const long*	imap,
    const void* values
));
extern int ncvargetg	PROTO((
    int		ncid,
    int		varid,
    const long*	start,
    const long*	count,
    const long*	stride,
    const long*	imap,
    void*	values
));
extern int ncvarrename	PROTO((
    int		ncid,
    int		varid,
    const char*	name
));
extern int ncattput	PROTO((
    int		ncid,
    int		varid,
    const char*	name, 
    nc_type	datatype,
    int		len,
    const void*	value
));
extern int ncattinq	PROTO((
    int		ncid,
    int		varid,
    const char*	name, 
    nc_type*	datatype,
    int*	len
));
extern int ncattget	PROTO((
    int		ncid,
    int		varid,
    const char*	name, 
    void*	value
));
extern int ncattcopy	PROTO((
    int		incdf,
    int		invar,
    const char*	name, 
    int		outcdf,
    int		outvar
));
extern int ncattname	PROTO((
    int		ncid,
    int		varid,
    int		attnum,
    char*	name
));
extern int ncattrename	PROTO((
    int		ncid,
    int		varid,
    const char*	name, 
    const char*	newname
));
extern int ncattdel	PROTO((
    int		ncid,
    int		varid,
    const char*	name
));
extern int nctypelen	PROTO((
    nc_type	datatype
));
extern int ncsetfill	PROTO((
    int		ncid,
    int		fillmode
));
extern int ncrecinq		PROTO((
    int		ncid,
    int*	nrecvars,
    int*	recvarids,
    long*	recsizes
));
extern int ncrecget		PROTO((
    int		ncid,
    long	recnum,
    void**	datap
));
extern int ncrecput		PROTO((
    int		ncid,
    long	recnum,
    void* const* datap
));

#ifdef __cplusplus
}
#endif

#endif /* _NETCDF_ */
