/*
* Copyright 1993, University Corporation for Atmospheric Research
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
*/
/* $Id: cdf.c,v 1.79 2003/12/10 21:15:10 epourmal Exp $ */
#include "local_nc.h"
#include "alloc.h"
#ifdef HDF
#include "hfile.h"
extern intn hdf_xdr_cdf
PROTO((XDR *xdrs, NC**handlep));
/* A couple of local prototypes to HDF section*/
intn hdf_cdf_clobber(NC *handle);
intn hdf_close(NC *handle);
static intn
hdf_num_attrs(NC *handle,/* IN: handle to SDS */
int32 vg /* IN: ref of top Vgroup */);
#endif /* HDF */
static bool_t NC_xdr_cdf(XDR *xdrs, NC **handlep);
static int NC_free_xcdf(NC *);
/* hmm we write the NDG out always for now */
#define WRITE_NDG 1
/* Debugging: define for each function you want debugging printfs */
/* #define HDF_READ_VARS
#define HDF_READ_ATTRS
#define HDF_NUM_ATTRS
#define HDF_XDR_CDF
#define HDF_VG_CLOBBER
#define HDF_CDF_CLOBBER
#define HDF_CLOSE */
/*
* free the stuff that xdr_cdf allocates
*
* NOTE: Modified to return SUCCEED / FAIL and to catch errors
* -GV 9/16/97
*/
static int
NC_free_xcdf(handle)
NC *handle ;
{
int ret_value = SUCCEED;
if(handle != NULL)
{
if (NC_free_array(handle->dims) == FAIL)
{
ret_value = FAIL;
goto done;
}
if (NC_free_array(handle->attrs) == FAIL)
{
ret_value = FAIL;
goto done;
}
if (NC_free_array(handle->vars) ==FAIL)
{
ret_value = FAIL;
goto done;
}
}
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
return ret_value;
}
/*
* NOTE: Modified to return SUCCEED / FAIL and to catch errors
* -GV 9/16/97
*/
int
NC_free_cdf(handle)
NC *handle ;
{
int ret_value = SUCCEED;
if(handle != NULL)
{
if (NC_free_xcdf(handle) == FAIL)
{
ret_value = FAIL;
goto done;
}
/* destroy xdr struct */
xdr_destroy(handle->xdrs);
Free(handle->xdrs);
#ifdef HDF
if(handle->file_type == HDF_FILE)
{
if (Vend(handle->hdf_file) == FAIL)
{
ret_value = FAIL;
goto done;
}
if (Hclose(handle->hdf_file) == FAIL)
{
ret_value = FAIL;
goto done;
}
}
#endif /* HDF */
Free(handle);
}
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
return ret_value;
}
#ifdef HDF
/******************************************************************************/
/*
From NASA CDF Source
*/
#define V2_MAGIC_NUMBER 0x0000FFFF /* Written twice at the beginning of file */
#define V2_MAGIC_OFFSET 0
/* -------------------------------- Hiscdf -------------------------------- */
/*
Return TRUE/FALSE depending on if the given file is a NASA CDF file
*/
PRIVATE intn
Hiscdf(filename)
const char * filename;
{
static const char *FUNC = "Hiscdf";
hdf_file_t fp;
uint8 b[4];
uint8 * bb = NULL;
int32 magic_num;
intn ret_value = TRUE;
fp = (hdf_file_t)HI_OPEN(filename, DFACC_READ);
if (OPENERR(fp))
{
ret_value = FALSE;
goto done;
}
else
{
if(HI_SEEK(fp, V2_MAGIC_OFFSET) == FAIL)
{
HERROR(DFE_SEEKERROR);
ret_value = FALSE;
goto done;
}
if(HI_READ(fp, b, 4) == FAIL)
{
HERROR(DFE_READERROR);
ret_value = FALSE;
goto done;
}
bb = &b[0];
INT32DECODE(bb, magic_num);
if(magic_num == V2_MAGIC_NUMBER)
ret_value = TRUE;
else
ret_value = FALSE;
HI_CLOSE(fp);
}
done:
if (ret_value == FALSE)
{ /* FALSE cleanup ?*/
}
/* Normal cleanup */
return ret_value;
}
/*
Model after Hiscdf
*/
/* -------------------------------- Hisnetcdf -------------------------------- */
/*
Return TRUE if the given file is a netCDF file, FALSE otherwise.
*/
PRIVATE intn
Hisnetcdf(filename)
const char * filename;
{
static const char *FUNC = "Hisnetcdf";
hdf_file_t fp;
uint8 b[4];
uint8 * bb = NULL;
int32 magic_num;
intn ret_value = TRUE;
fp = (hdf_file_t)HI_OPEN(filename, DFACC_READ);
if (OPENERR(fp))
{
ret_value = FALSE;
goto done;
}
else
{
if(HI_READ(fp, b, 4) == FAIL)
{
HERROR(DFE_READERROR);
HI_CLOSE(fp);
ret_value = FALSE;
goto done;
}
bb = &b[0];
INT32DECODE(bb, magic_num);
if(magic_num == NCMAGIC)
ret_value = TRUE;
else
ret_value = FALSE;
HI_CLOSE(fp);
}
done:
if (ret_value == FALSE)
{ /* FALSE cleanup? */
}
/* Normal cleanup */
return ret_value;
}
/******************************************************************************/
#endif /* HDF */
/*
* NOTE: Cleaned up to catch errors - GV 9/19/97
*/
NC *
NC_new_cdf(name, mode)
const char *name ;
int mode ;
{
#ifdef HDF
int32 hdf_mode = DFACC_RDWR; /* default */
#endif
NC *cdf = NULL;
static const char *FUNC = "NC_new_cdf";
NC *ret_value = NULL;
/* allocate an NC struct */
cdf = (NC *)HDcalloc(1,sizeof(NC)) ;
if( cdf == NULL )
{
nc_serror("NC_new_cdf") ;
ret_value = NULL;
goto done;
}
cdf->flags = mode ;
cdf->xdrs = (XDR *)HDmalloc(sizeof(XDR)) ;
if( cdf->xdrs == NULL)
{
nc_serror("NC_new_cdf: xdrs") ;
ret_value = NULL;
goto done;
} /* else */
#ifdef HDF
/*
* See what type of file we are looking at.
* If we are creating a new file it will be an HDF file
*/
if(mode & NC_CREAT)
{
cdf->file_type = HDF_FILE;
}
else
{
if(Hishdf(name))
cdf->file_type = HDF_FILE;
else if(Hiscdf(name))
cdf->file_type = CDF_FILE;
else if(Hisnetcdf(name))
cdf->file_type = netCDF_FILE;
else
{
ret_value = NULL;
goto done;
}
#ifdef DEBUG
if(cdf->file_type == CDF_FILE)
printf("Yow! found a CDF file\n");
#endif
}
/*
* Set up the XDR functions that some of the netCDF old code uses
*/
switch(cdf->file_type)
{
case HDF_FILE:
hdf_xdrfile_create(cdf->xdrs, mode); /* return type is 'void' */
break;
case netCDF_FILE:
if( NCxdrfile_create( cdf->xdrs, name, mode ) < 0)
{
ret_value = NULL;
goto done;
}
break;
case CDF_FILE:
/* CDF_xdrfile_create(); */
/* try this, I bet it will be sufficient */
hdf_xdrfile_create(cdf->xdrs, mode);
break;
}
#else /* !HDF */
if( NCxdrfile_create( cdf->xdrs, name, mode ) < 0)
{
ret_value = NULL;
goto done;
}
#endif /* !HDF */
cdf->dims = NULL ;
cdf->attrs = NULL ;
cdf->vars = NULL ;
cdf->begin_rec = 0 ;
cdf->recsize = 0 ;
cdf->numrecs = 0 ;
cdf->redefid = -1 ;
#ifdef HDF
/*
* determine the HDF access mode
*/
switch(mode)
{
case NC_CLOBBER :
hdf_mode = DFACC_CLOBBER; break;
case NC_NOCLOBBER :
/* will handle below */
break;
case NC_WRITE :
hdf_mode = DFACC_RDWR; break;
case NC_NOWRITE :
hdf_mode = DFACC_RDONLY; break;
default:
hdf_mode = DFACC_RDWR;
}
/*
* Do file type specific setup
*/
switch(cdf->file_type)
{
case HDF_FILE: /* HDF stuff */
/* see if the file exists */
if(mode == NC_NOCLOBBER)
{
if((int) Hishdf(name))
{ /* Need to free allocated structures.
This will happen on failure cleanup. */
xdr_destroy(cdf->xdrs) ; /* destroy xdr struct first */
ret_value = NULL;
goto done;
}
hdf_mode = DFACC_RDWR;
}
/* open the file */
cdf->hdf_file = (int32) Hopen(name, hdf_mode, 200);
if(cdf->hdf_file == FAIL)
{
ret_value = NULL;
goto done;
}
/* start Vxx access */
if (Vstart(cdf->hdf_file) == FAIL)
{
ret_value = NULL;
goto done;
}
cdf->hdf_mode = hdf_mode;
cdf->vgid = 0; /* invalid ref */
HDstrncpy(cdf->path, name, FILENAME_MAX);
#if 0
HDmemcpy(cdf->path, name, FILENAME_MAX);
#endif
#ifdef DEBUG
printf("value returned from Hopen() : %d\n", cdf->hdf_file);
#endif
break;
case netCDF_FILE:
/* Nothing */
break;
case CDF_FILE:
#ifdef DEBUG
fprintf(stderr, "About to do CDF file set up\n");
#endif
cdf->cdf_fp = (hdf_file_t) HI_OPEN(name, hdf_mode);
if (OPENERR(cdf->cdf_fp))
HRETURN_ERROR(DFE_DENIED,NULL);
break;
}
#endif /* HDF */
/*
* Read in the contents
*/
if(cdf->xdrs->x_op == XDR_DECODE) /* Not NC_CREAT */
{
if(!xdr_cdf(cdf->xdrs, &cdf) )
{ /* free cdf struct. This cleanup is different than
NC_free_xcdf(). */
NC_free_cdf(cdf); /* free memory, close structues,files etc*/
cdf = NULL;
ret_value = NULL ;
goto done;
}
if(NC_computeshapes(cdf) == -1)
{
ret_value = NULL;
goto done;
}
}
ret_value = cdf ;
done:
if (ret_value == NULL)
{ /* Failure cleanup */
if (cdf != NULL)
{ /* handles case other than one for NC_free_cdf().
These routines only free up allocted memory. */
NC_free_xcdf(cdf); /* no point in catching error here */
if (cdf->xdrs != NULL)
Free(cdf->xdrs);
Free(cdf) ;
}
}
/* Normal cleanup */
return ret_value;
}
/*
* Duplicate a description structure.
* Can only be called for 'old' extant on disk, eg, old in DATA mode.
*
* NOTE: Cleaned up to catch errors - GV 9/19/97
*/
NC *
NC_dup_cdf(name, mode, old)
const char *name ;
int mode ;
NC *old ;
{
NC *cdf = NULL;
NC *ret_value = NULL;
cdf = (NC *)HDmalloc(sizeof(NC)) ;
if( cdf == NULL )
{
nc_serror("NC_dup_cdf") ;
ret_value = NULL;
goto done;
}
cdf->flags = old->flags | NC_INDEF ;
cdf->xdrs = (XDR *)HDmalloc(sizeof(XDR)) ;
if( cdf->xdrs == NULL)
{
nc_serror("NC_dup_cdf: xdrs") ;
ret_value = NULL;
goto done;
}
cdf->dims = NULL ;
cdf->attrs = NULL ;
cdf->vars = NULL ;
cdf->begin_rec = 0 ;
cdf->recsize = 0 ;
cdf->numrecs = 0 ;
#ifdef HDF
cdf->file_type = old->file_type;
#endif
if(NCxdrfile_create( cdf->xdrs, name, mode) < 0)
{
ret_value = NULL ;
goto done;
}
old->xdrs->x_op = XDR_DECODE ;
if(!xdr_cdf(old->xdrs, &cdf) )
{
ret_value = NULL;
goto done;
}
if( NC_computeshapes(cdf) == -1)
{
ret_value = NULL;
goto done;
}
ret_value = cdf;
done:
if (ret_value == NULL)
{ /* Failure cleanup */
if (cdf != NULL)
{ /* free up allocated structures */
if (cdf->xdrs != NULL)
Free(cdf->xdrs);
NC_free_xcdf(cdf); /* don't catch error here */
Free(cdf);
}
}
/* Normal cleanup */
return ret_value;
}
int ncinquire(cdfid, ndimsp, nvarsp, nattrsp, xtendimp)
int cdfid ;
int *ndimsp ;
int *nvarsp ;
int *nattrsp ;
int *xtendimp ;
{
NC *handle ;
cdf_routine_name = "ncinquire" ;
handle = NC_check_id(cdfid) ;
if(handle == NULL)
return(-1) ;
if(nvarsp != NULL)
*nvarsp = (handle->vars != NULL) ? handle->vars->count : 0 ;
if(nattrsp != NULL)
*nattrsp = (handle->attrs != NULL) ? handle->attrs->count : 0 ;
if(handle->dims != NULL)
{
NC_dim **dp ;
int ii ;
if(ndimsp != NULL)
*ndimsp = handle->dims->count ;
if(xtendimp != NULL) {
*xtendimp = -1 ;
dp = (NC_dim**)handle->dims->values ;
for(ii = 0 ; ii < handle->dims->count ; ii++, dp++)
{
if((*dp)->size == NC_UNLIMITED)
{
*xtendimp = ii ;
}
}
}
} else {
if(ndimsp != NULL)
*ndimsp = 0 ;
if(xtendimp != NULL)
*xtendimp = -1 ;
}
return(cdfid) ;
}
/*
* NOTE: modfied how errors were caught and reported - GV 9/19/97
*/
bool_t
xdr_cdf(xdrs, handlep)
XDR *xdrs;
NC **handlep;
{
bool_t ret_value = TRUE;
#ifdef HDF
switch((*handlep)->file_type)
{
case HDF_FILE:
if (hdf_xdr_cdf(xdrs, handlep) == FAIL)
ret_value = FALSE;
break;
case netCDF_FILE:
ret_value = NC_xdr_cdf(xdrs, handlep);
break;
case CDF_FILE:
ret_value = nssdc_xdr_cdf(xdrs, handlep);
break;
default:
ret_value = FALSE;
break;
}
#else /* !HDF */
ret_value = NC_xdr_cdf(xdrs, handlep);
#endif /* !HDF */
return ret_value;
}
static bool_t
NC_xdr_cdf(xdrs, handlep)
XDR *xdrs;
NC **handlep;
{
u_long magic;
if( xdrs->x_op == XDR_FREE)
{
NC_free_xcdf(*handlep) ;
return(TRUE) ;
}
if( xdr_getpos(xdrs) != 0)
{
if( !xdr_setpos(xdrs, 0) )
{
nc_serror("Can't set position to begin") ;
return(FALSE) ;
}
}
/* magic number */
if( !xdr_u_long(xdrs, &magic) )
{
if( xdrs->x_op == XDR_DECODE)
{
NCadvise(NC_ENOTNC,
"Not a netcdf file (Can't read magic number)") ;
}
else
{
/* write error */
nc_serror("xdr_cdf: xdr_u_long") ;
}
return(FALSE) ;
}
if( xdrs->x_op == XDR_DECODE && magic != NCMAGIC )
{
if(magic == NCLINKMAGIC)
{
NCadvise(NC_NOERR, "link file not handled yet") ;
return(FALSE) ;
} /* else */
NCadvise(NC_ENOTNC, "Not a netcdf file") ;
return(FALSE) ;
}
if( !xdr_numrecs(xdrs, *handlep))
{
NCadvise(NC_EXDR, "xdr_numrecs") ;
return(FALSE) ;
}
if( !xdr_NC_array(xdrs, &((*handlep)->dims)))
{
NCadvise(NC_EXDR, "xdr_cdf:dims") ;
return(FALSE) ;
}
if( !xdr_NC_array(xdrs, &((*handlep)->attrs)))
{
NCadvise(NC_EXDR, "xdr_cdf:attrs") ;
return(FALSE) ;
}
if( !xdr_NC_array(xdrs, &((*handlep)->vars)))
{
NCadvise(NC_EXDR, "xdr_cdf:vars") ;
return(FALSE) ;
}
return(TRUE) ;
}
#ifdef HDF
/*****************************************************************************
*
* NCSA HDF / netCDF Project
* May, 1993
*
* NCSA HDF / netCDF source code and documentation are in the public domain.
* Specifically, we give to the public domain all rights for future
* licensing of the source code, all resale rights, and all publishing rights.
*
* We ask, but do not require, that the following message be included in all
* derived works:
*
* Portions developed at the National Center for Supercomputing Applications at
* the University of Illinois at Urbana-Champaign. Funding for this project
* has come primarily from the National Science Foundation.
*
* THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
* SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
* WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
*
******************************************************************************
*
* Please report all bugs / comments to hdfhelp@ncsa.uiuc.edu
*
*****************************************************************************/
/* ----------------------------------------------------------------
** Map an NC_<type> to an HDF type
*/
int
hdf_map_type(type)
nc_type type;
{
switch(type)
{
case NC_UNSPECIFIED : /* be like netCDF */
case NC_CHAR :
return DFNT_CHAR;
case NC_BYTE :
return DFNT_INT8;
case NC_SHORT :
return DFNT_INT16;
case NC_LONG :
return DFNT_INT32;
case NC_FLOAT :
return DFNT_FLOAT32;
case NC_DOUBLE :
return DFNT_FLOAT64;
default:
return DFNT_NONE;
}
} /* hdf_map_type */
/* ----------------------------------------------------------------
** UnMap a data type. I.e. go from an HDF type to an NC_<type>
** The HDF type may be in DFNT_NATIVE mode, so only look at the
** bottom bits
*/
nc_type
hdf_unmap_type(type)
int type;
{
switch(type & 0xff)
{
case DFNT_CHAR :
case DFNT_UCHAR :
return NC_CHAR;
case DFNT_INT8 :
case DFNT_UINT8 :
return NC_BYTE;
case DFNT_INT16 :
case DFNT_UINT16 :
return NC_SHORT;
case DFNT_INT32 :
case DFNT_UINT32 :
return NC_LONG;
case DFNT_FLOAT32 :
return NC_FLOAT;
case DFNT_FLOAT64 :
return NC_DOUBLE;
default:
return (nc_type)FAIL; /* need a better legal nc_type value */
}
} /* hdf_unmap_type */
/* -----------------------------------------------------------------
** Given a dimension id number return its hdf_ref number (Vgroup id)
*/
int
hdf_get_ref(handle, i)
NC *handle;
int i;
{
NC_array *tmp = NULL;
NC_dim **d = NULL;
Void *dims = NULL;
tmp = handle->dims;
dims = handle->dims->values;
dims += i * tmp->szof;
d = (NC_dim **) dims;
return (*d)->vgid; /* return ref of vgroup */
} /* get_hdf_ref */
/* ----------------------------------------------------------------
** Given a dimension pointer return the ref of a Vdata which was
** newly created to represent the values the dimension takes on
** If there is a variable with the same name as our dimension then
** the values the variable takes on are the values for the
** 'steps' in the dimension.
** Otherwise, the dimension takes on the values 0..(size -1)
**
** NOTE: This may cause conflicts cuz we may get called before
** the variable's values are set???
**
** NOTE2: Someone should update the comments here. They no longer
** seem valid -GV 9/19/97
*/
int
hdf_create_dim_vdata(xdrs, handle, dim)
XDR *xdrs;
NC *handle;
NC_dim *dim;
{
#ifdef LATER
CONSTR(FUNC,"hdf_create_dim_vdata");
#endif /* LATER */
int found = FALSE;
int ref;
int32 val;
long dsize;
int ret_value = FAIL;
#if DEBUG
fprintf(stderr, "hdf_create_dim_vdata I've been called\n");
fprintf(stderr, "handle->hdf_file = %d\n", handle->hdf_file);
#endif
#if 0
/* look for variable with the given name */
if(handle->vars)
{
dp = (NC_var **) handle->vars->values;
for(ii = 0; ii < handle->vars->count; ii++, dp++)
if(HDstrcmp(dim->name->values, (*dp)->name->values) == 0)
{
/* found it */
found = TRUE;
break;
}
}
#endif
if(found)
{
/* load in the variable's values */
#if DEBUG
fprintf(stderr, "Found real values for dimension %s\n", dim->name->values);
#endif
}
else
{
dsize = 1;
val = (dim->size != NC_UNLIMITED) ? dim->size : (int32)handle->numrecs;
ref = VHstoredata(handle->hdf_file, "Values", (const uint8 *)&val, dsize,
DFNT_INT32, dim->name->values, DIM_VALS01);
if(ref == FAIL)
{
#ifdef DEBUG
fprintf(stderr, "FAILed creating Vdata %s\n", dim->name->values);
#endif
ret_value = FAIL;
goto done;
}
}
#if DEBUG
fprintf(stderr, "Returning vdata pointer %d\n", ref);
#endif
ret_value = ref;
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
return ret_value;
} /* hdf_create_dim_vdata */
/* ----------------------------------------------------------------
** Given a dimension pointer return the ref of an older version
** dim Vdata which was newly created to represent the values
** the dimension takes on, for backward compatibility.
**
** For DIM_VALS, the values the variable takes on are the values
** for the 'steps' in the dimension.
**
*/
int
hdf_create_compat_dim_vdata(XDR *xdrs,
NC *handle,
NC_dim *dim,
int32 dimval_ver)
{
static const char *FUNC = "hdf_create_compat_dim_vdata";
int i;
int ref;
long dsize;
int32 *val = NULL;
int ret_value = FAIL;
#ifdef DEBUG
fprintf(stderr, "hdf_create_compat_dim_vdata I've been called\n");
fprintf(stderr, "handle->hdf_file = %d\n", handle->hdf_file);
fprintf(stderr, "dim_ver = %d\n", dim_ver);
#endif
if (dimval_ver != DIMVAL_VERSION00)
{
ret_value = FAIL;
goto done;
}
dsize = (dim->size == NC_UNLIMITED)? 1 : dim->size;
if (dsize < 0)
{
ret_value = FAIL;
goto done;
}
/* create a fake one */
#ifdef DEBUG
fprintf(stderr, "Creating fake dim ::::%s::: (%d)\n",
dim->name->values, dsize);
#endif
/* allocate space */
val = (int32 *) HDmalloc(dsize * sizeof(int32));
if(!val)
{
HERROR(DFE_NOSPACE);
ret_value = FAIL;
goto done;
}
if (dim->size == NC_UNLIMITED)
{
*val = handle->numrecs;
}
else
{
for(i = 0; i < dsize; i++) val[i] = i;
}
ref = VHstoredata(handle->hdf_file, "Values", (const uint8 *)val,
dsize, DFNT_INT32, dim->name->values, DIM_VALS);
if(ref == FAIL)
{
#ifdef DEBUG
fprintf(stderr, "FAILed creating Vdata %s\n", dim->name->values);
#endif
ret_value = FAIL;
goto done;
}
#ifdef DEBUG
fprintf(stderr, "Returning vdata pointer %d\n", ref);
#endif
ret_value = ref;
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
if (val != NULL)
HDfree(val);
return ret_value;
} /* hdf_create_compat_dim_vdata */
/* ----------------------------------------------------------------
** Write out a vdata representing an attribute
*/
int
hdf_write_attr(xdrs, handle, attr)
XDR *xdrs;
NC *handle;
NC_attr **attr;
{
char *name = NULL;
Void *values = NULL;
int size;
int type;
int order;
int ret_value = SUCCEED;
name = (*attr)->name->values;
values = (*attr)->data->values;
size = (*attr)->data->count;
type = (*attr)->HDFtype;
#if DEBUG
fprintf(stderr, "hdf_write_attr I've been called\n");
fprintf(stderr, "The attribute is called %s\n", name);
fprintf(stderr, "Type = %d (%d) size %d\n", type, (*attr)->HDFtype, size);
fprintf(stderr, "Value: ");
switch(type)
{
case DFNT_CHAR :fprintf(stderr, " (char) %s\n", (char *) values); break;
case DFNT_UINT8 :fprintf(stderr, " (uint8) %d\n", (char *) values); break;
case DFNT_INT8 :fprintf(stderr, " (int8) %d\n", (char *) values); break;
case DFNT_UINT16 :fprintf(stderr, " (uint16) %d\n", (int *) values); break;
case DFNT_INT16 :fprintf(stderr, " (int16) %d\n", (int *) values); break;
case DFNT_UINT32 :fprintf(stderr, " (uint32) %d\n", (int *) values); break;
case DFNT_INT32 :fprintf(stderr, " (int32) %d\n", (int *) values); break;
case DFNT_FLOAT32 :fprintf(stderr, " (float32) %f\n", (float *) values); break;
case DFNT_FLOAT64 :fprintf(stderr, " (float64) %f\n", (double *) values); break;
default:fprintf(stderr, "???\n");
}
#endif
if(type == DFNT_CHAR)
{
order = size;
size = 1;
}
else
{
order = 1;
}
ret_value = VHstoredatam(handle->hdf_file, ATTR_FIELD_NAME,
(unsigned char *) values, size,
type, name, _HDF_ATTRIBUTE, order);
#if DEBUG
fprintf(stderr, "hdf_write_attr returning %d\n", ret_value);
#endif
#ifdef LATER
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
#endif /* LATER */
return ret_value;
} /* hdf_write_attr */
/* ----------------------------------------------------------------
** Write out a group representing a dimension
*/
int32
hdf_write_dim(XDR *xdrs, NC *handle, NC_dim **dim, int32 cnt)
{
int32 tags[100];
int32 refs[100];
int32 count;
const char *class = NULL;
char name[MAX_NC_NAME] = "";
int32 ret_value = SUCCEED;
#if DEBUG
fprintf(stderr, "hdf_write_dim I've been called\n");
fprintf(stderr, "The name is -- %s -- \n", (*dim)->name->values);
#endif
/*
* Look up to see if there is a variable of the same name
* giving values
*/
count = 0;
tags[count] = DFTAG_VH;
refs[count] = hdf_create_dim_vdata(xdrs, handle, (*dim));
if(refs[count] == FAIL)
{
ret_value = FAIL;
goto done;
}
count++;
/* do we need to create compatible dimension? */
if ((*dim)->dim00_compat)
{
tags[count] = DFTAG_VH;
refs[count] = hdf_create_compat_dim_vdata(xdrs, handle, (*dim), DIMVAL_VERSION00);
if(refs[count] == FAIL)
{
ret_value = FAIL;
goto done;
}
count++;
}
/* check if UNLIMITED dimension */
if((*dim)->size == NC_UNLIMITED)
class = _HDF_UDIMENSION;
else
class = _HDF_DIMENSION;
if(HDstrncmp((*dim)->name->values, "fakeDim", 7) == 0)
sprintf(name, "fakeDim%d", (int)cnt);
else
HDstrcpy(name, (*dim)->name->values);
/* write out the dimension group? */
(*dim)->vgid = VHmakegroup(handle->hdf_file, tags, refs, count,
name, class);
ret_value = (*dim)->vgid; /* ref of vgroup of dimension */
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
return ret_value;
} /* hdf_write_dim */
/* ----------------------------------------------------------------
** Write out a group representing a variable
** If successfull, return the id of the created Vgroup else
** return NULL
*/
int32
hdf_write_var(xdrs, handle, var)
XDR *xdrs;
NC *handle;
NC_var **var;
{
NC_array * attrs = NULL;
NC_iarray * assoc = NULL;
uint8 ntstring[4];
uint16 ref;
int8 outNT;
uint8 tbuf[2+((MAX_VAR_DIMS+1)*8)]; /* temporary buffer */
int32 tags[MAX_NC_ATTRS + MAX_VAR_DIMS + 2];
int32 refs[MAX_NC_ATTRS + MAX_VAR_DIMS + 10];
uint16 nt_ref, rank;
int32 GroupID, val;
uint8 *bufp = NULL;
#ifdef LATER
CONSTR(FUNC,"hdf_write_var");
#endif /* LATER */
int32 ret_value = SUCCEED;
register int i, count;
register Void *attribute = NULL;
count = 0;
assoc = (*var)-> assoc;
attrs = (*var)-> attrs;
#if DEBUG
fprintf(stderr, "hdf_write_var I've been called\n");
fprintf(stderr, "handle->hdf_file = %d\n", handle->hdf_file);
fprintf(stderr, "The name is -- %s -- \n", (*var)->name->values);
if(assoc && assoc->count)
{
fprintf(stderr, "value of assoc %d\n", assoc);
fprintf(stderr, " assoc->count %d\n", assoc->count);
fprintf(stderr, " asc[0] %d asc[1] %d\n", assoc->values[0], assoc->values[1]);
}
#endif
/*
* Get the dimension information
*/
for(i = 0; i < assoc->count; i++)
{
tags[count] = DIM_TAG;
refs[count] = hdf_get_ref(handle, assoc->values[i]);
count++;
}
/*
* Add info for the attributes
*/
if(attrs)
{
attribute = attrs->values;
for(i = 0; i < attrs->count; i++)
{
tags[count] = ATTR_TAG;
refs[count] = hdf_write_attr(xdrs, handle, (NC_attr **)attribute);
if (refs[count] == FAIL)
{
ret_value = FAIL;
goto done;
}
attribute += attrs->szof;
count++;
}
}
/*
* If we already have data written out include that too
* (this might happen after a redef() cuz we will leave
* the data sitting on the disk but clear out all the
* meta-data)
*/
if((*var)->data_ref)
{
tags[count] = (int32) DFTAG_SD;
refs[count] = (*var)->data_ref;
#if DEBUG
fprintf(stderr, " ---- Carrying forward data with ref %d ---- \n", (*var)->data_ref);
#endif
count++;
}
/*
* Write out a number type tag so that we can recover this
* variable's type later on
*
* by default numbers are converted to IEEE otherwise we need to save the
* machine type in the NT object
*/
/* somone unwrap this statement....*/
outNT = ((*var)->HDFtype & DFNT_NATIVE)?
DFKgetPNSC((*var)->HDFtype, DF_MT) : ((*var)->HDFtype & DFNT_LITEND)?
DFNTF_PC : DFNTF_IEEE;
#ifdef NOT_YET
ref = Htagnewref(handle->hdf_file,DFTAG_NT);
#else /* NOT_YET */
ref = Hnewref(handle->hdf_file);
#endif /* NOT_YET */
ntstring[0] = DFNT_VERSION; /* version */
ntstring[1] = (uint8)((*var)->HDFtype & 0xff); /* type */
ntstring[2] = (uint8)((*var)->HDFsize * 8); /* width (in bits) */
ntstring[3] = outNT; /* class: IEEE or machine class */
if(Hputelement(handle->hdf_file, DFTAG_NT, ref, ntstring, (int32) 4) == FAIL)
{
ret_value = FAIL;
goto done;
}
tags[count] = DFTAG_NT;
refs[count] = ref;
nt_ref = (uint16) ref;
count++;
#ifdef WRITE_NDG
/* prepare to start writing ndg */
if ((GroupID = DFdisetup(10)) < 0)
{
ret_value = FAIL;
goto done;
}
/* write SD record */
if((*var)->data_ref)
{
if (DFdiput(GroupID, DFTAG_SD, (uint16) (*var)->data_ref) == FAIL)
{
ret_value = FAIL;
goto done;
}
}
/* write NT tag/ref */
if (DFdiput(GroupID, DFTAG_NT, (uint16) ref) == FAIL)
{
ret_value = FAIL;
goto done;
}
/* put rank & dimensions in buffer */
bufp = tbuf;
rank = assoc->count;
UINT16ENCODE(bufp, rank);
for(i = 0; i < (int)rank; i++)
{
val = (int32) (*var)->shape[i];
/* need to fake the size of the record dimension */
if(val == NC_UNLIMITED)
{
if(handle->file_type == HDF_FILE)
val = (*var)->numrecs;
else
val = handle->numrecs;
}
INT32ENCODE(bufp, val);
}
/* "<=" used to put 1 data NT + rank scale NTs in buffer */
for (i = 0; i <= (int)rank; i++)
{ /* scale NTs written even if no scale!*/
UINT16ENCODE(bufp, DFTAG_NT);
UINT16ENCODE(bufp, nt_ref);
}
/* write out SDD record */
if(Hputelement(handle->hdf_file, DFTAG_SDD, ref, tbuf, (int32) (bufp-tbuf)) == FAIL)
{
ret_value = FAIL;
goto done;
}
/* write dimension record tag/ref */
if (DFdiput(GroupID, DFTAG_SDD,(uint16) ref) == FAIL)
{
ret_value = FAIL;
goto done;
}
tags[count] = DFTAG_SDD;
refs[count] = ref;
count++;
/* Add a bogus tag so we know this NDG is really a variable */
if (DFdiput(GroupID, BOGUS_TAG,(uint16) ref) == FAIL)
{
ret_value = FAIL;
goto done;
}
/* write out NDG */
if (DFdiwrite(handle->hdf_file, GroupID, DFTAG_NDG, (*var)->ndg_ref) < 0)
{
ret_value = FAIL;
goto done;
}
tags[count] = DFTAG_NDG;
refs[count] = (*var)->ndg_ref;
count++;
#endif /* WRITE_NDG */
/* write the vgroup for the variable ? */
(*var)->vgid = VHmakegroup(handle->hdf_file, tags, refs, count,
(*var)->name->values, _HDF_VARIABLE);
#ifdef DEBUG
if((*var)->vgid == FAIL)
{
fprintf(stderr, "Failed to write variable %s\n", (*var)->name->values);
fprintf(stderr, "count = %d\n", count);
for(i = 0; i < count; i++)
fprintf(stderr, "i = %d tag = %d ref = %d\n", i, tags[i], refs[i]);
HEprint(stdout, 0);
}
#endif
ret_value = (*var)->vgid; /* ref of vgroup of variable */
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
return ret_value;
} /* hdf_write_var */
/* ----------------------------------------------------------------
** Write out a cdf structure
*/
intn
hdf_write_xdr_cdf(xdrs, handlep)
XDR *xdrs;
NC **handlep;
{
int32 count;
int sz, i, j, status, done;
int32 *tags = NULL;
int32 *refs = NULL;
NC_dim **dims = NULL;
NC_dim **dims1 = NULL;
NC_array *tmp = NULL;
long *dim_size_array = NULL;
long *tsizeptr = NULL;
long tsize;
uint32 *dim_hash_array = NULL;
uint32 *thashptr = NULL;
uint32 thash;
Void *vars = NULL;
Void *attrs = NULL;
intn ret_value = SUCCEED;
#if DEBUG
fprintf(stderr, "hdf_write_xdr_cdf i've been called op = %d \n", xdrs->x_op);
#endif
/* Convert old scales into coordinate var values before writing
out any header info */
status = hdf_conv_scales(handlep);
if (status == FAIL)
{
ret_value = FAIL;
goto done;
}
/* count size of tag / ref arrays */
sz = 0;
if((*handlep)->dims)
sz += (*handlep)->dims->count;
if((*handlep)->vars)
sz += (*handlep)->vars->count;
if((*handlep)->attrs)
sz += (*handlep)->attrs->count;
#if DEBUG
fprintf(stderr, "sz = %d\n", sz);
#endif
/* allocate tag / ref arrays */
tags = (int32 *) HDmalloc(sz * sizeof(int32) + 1);
refs = (int32 *) HDmalloc(sz * sizeof(int32) + 1);
if(NULL == tags || NULL == refs)
{
#ifdef DEBUG
fprintf(stderr, "Out of memory line %d file %s\n", __LINE__, __FILE__);
#endif
ret_value = FAIL;
goto done;
}
/*
** write out dimension arrays
*/
count = 0;
if((*handlep)->dims)
{
tmp = (*handlep)->dims;
dims = (NC_dim **) (*handlep)->dims->values;
tsizeptr = dim_size_array =(long *)HDmalloc(sizeof(long)*(size_t)tmp->count);
thashptr = dim_hash_array =(uint32 *)HDmalloc(sizeof(uint32)*(size_t)tmp->count);
if(NULL == dim_size_array || NULL == dim_hash_array)
{
#ifdef DEBUG
fprintf(stderr, "Out of memory line %d file %s\n", __LINE__, __FILE__);
#endif
ret_value = FAIL;
goto done;
}
for(i = 0; i < tmp->count; i++,dims++)
{
*tsizeptr++=(*dims)->size;
*thashptr++=(*dims)->name->hash;
} /* end for */
dims = (NC_dim **) (*handlep)->dims->values;
for(i = 0; i < tmp->count; i++)
{
/* this is really ugly and should be handled another way */
/* make sure we don't duplicate dimensions */
done = FALSE;
dims1 = (NC_dim **) (*handlep)->dims->values;
tsize = dim_size_array[i];
thash = dim_hash_array[i];
tsizeptr = dim_size_array;
thashptr = dim_hash_array;
for(j = 0; j < i; j++)
{
/* this order on the test is faster -QAK */
if( thash == *thashptr
&& tsize == *tsizeptr
&& NC_compare_string((*dims)->name,(*dims1)->name) == 0 )
{
done = TRUE;
break;
}
tsizeptr++;
thashptr++;
dims1++;
}
if(!done)
{
tags[count] = (int32) DIM_TAG;
refs[count] = (int32) hdf_write_dim(xdrs, (*handlep), dims, count);
if(refs[count] == FAIL)
{
ret_value = FAIL;
goto done;
}
count++;
}
dims++;
}
} /* end if handle->dims */
/*
** write out variable info
*/
if((*handlep)->vars)
{
tmp = (*handlep)->vars;
vars = (*handlep)->vars->values;
for(i = 0; i < tmp->count; i++)
{
tags[count] = (int32) VAR_TAG;
refs[count] = (int32) hdf_write_var(xdrs, (*handlep), (NC_var **)vars);
if(refs[count] == FAIL)
{
ret_value = FAIL;
goto done;
}
vars += tmp->szof;
count++;
}
}
/*
* write global attribute information
*/
if((*handlep)->attrs)
{
tmp = (*handlep)->attrs;
attrs = (*handlep)->attrs->values;
for(i = 0; i < tmp->count; i++)
{
tags[count] = (int32) ATTR_TAG;
refs[count] = (int32) hdf_write_attr(xdrs, (*handlep), (NC_attr **)attrs);
if(refs[count] == FAIL)
{
ret_value = FAIL;
goto done;
}
attrs += tmp->szof;
count++;
}
}
#if DEBUG
fprintf(stderr, "About to write top level VG with %d elements\n", count);
{
int i;
for(i = 0; i < count; i++)
fprintf(stderr, "%d :=> %d %d\n", i, tags[i], refs[i]);
}
#endif
/* write out final VGroup thang */
/* set the top level CDF VGroup pointer */
(*handlep)->vgid = VHmakegroup((*handlep)->hdf_file, tags, refs, count,
(*handlep)->path, _HDF_CDF);
ret_value = (*handlep)->vgid; /* ref of final vgroup */
#ifdef DEBUG
fprintf(stderr, "======= Have finished writing top level VGroup #%d\n", ret_value);
#endif
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
if (dim_size_array != NULL)
HDfree(dim_size_array);
if (dim_hash_array != NULL)
HDfree(dim_hash_array);
if (tags != NULL)
HDfree(tags);
if (refs != NULL)
HDfree(refs);
return ret_value;
} /* hdf_write_xdr_cdf */
/* --------------------------------------------------------------
** hdf_conv_scales converts old scale values into coord var values.
** Searchs through var list for DFTAG_SDS, reads in the scale data,
** change the ref to ndg_ref and the tag to DATA_TAG, writes the
** data out.
*/
intn
hdf_conv_scales(handlep)
NC **handlep;
{
int i, status, scaleref, scaletag, scalelen;
NC_var **vars = NULL;
NC_array *tmp = NULL;
uint8 *scalebuf = NULL;
uint8 *datap = NULL;
intn ret_value = SUCCEED;
#ifdef LATER
CONSTR(FUNC, "hdf_conv_scales");
#endif /* LATER */
if ((*handlep)->vars)
{
tmp = (*handlep)->vars;
vars = (NC_var **)tmp->values;
for (i = 0; i < tmp->count; i++)
{
if ( ((*vars)->data_tag == DFTAG_SDS)
&& ((*vars)->data_ref != (*vars)->ndg_ref))
{
/* read in scale values */
scaleref = (*vars)->data_ref;
scaletag = (*vars)->data_tag;
scalelen = Hlength((*handlep)->hdf_file, scaletag, scaleref);
if (scalelen == FAIL)
{
ret_value = FAIL;
goto done;
}
if ((*vars)->data_offset == -1)
{ /* this dim has no scale values */
(*vars)->data_ref = 0;
(*vars)->data_tag = DATA_TAG;
}
else
{ /* has scale values */
scalebuf = (uint8 *)HDmalloc((uint32)scalelen);
if (scalebuf == NULL)
{
ret_value = FAIL;
goto done;
}
status = Hgetelement((*handlep)->hdf_file, scaletag,
scaleref, scalebuf);
if (status == FAIL)
{
ret_value = FAIL;
goto done;
}
(*vars)->data_tag = DATA_TAG;
(*vars)->data_ref = (*vars)->ndg_ref; /* Try to stick
with the current way. If this ref conflicts with
existing SDS, call Hnewref to get a new one. 3/25/97 */
datap = scalebuf + (*vars)->data_offset;
status = Hputelement((*handlep)->hdf_file, DATA_TAG,
(*vars)->data_ref, datap, (*vars)->len);
if (status == FAIL)
{
(*vars)->data_tag = scaletag;
(*vars)->data_ref = scaleref;
ret_value = FAIL;
goto done;
}
} /* has scale values */
} /* DFTAG_SDS */
vars ++;
}
}
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
if (scalebuf != NULL)
HDfree(scalebuf);
return ret_value;
}
/* ----------------------------------------------------------------
** Read in the dimensions out of a cdf structure
** Return FAIL if something goes wrong
*/
intn
hdf_read_dims(XDR *xdrs, NC *handle, int32 vg)
{
char vgname[MAX_NC_NAME] = "";
char vsclass[MAX_NC_CLASS] = "";
char vgclass[MAX_NC_CLASS] = "";
int id, count, i, found;
int sub_id;
int32 dim_size;
NC_dim **dimension = NULL;
int32 dim, entries;
int32 vs;
intn ret_value = SUCCEED;
found = FALSE;
count = 0;
id = -1;
#if DEBUG
fprintf(stderr, "hdf_read_dims I've been called, handle->hdf_file = %d\n", handle->hdf_file);
#endif
/*
* Allocate enough space in case everything is a dimension
*/
count = 0;
dimension = (NC_dim **) HDmalloc(sizeof(NC_dim *) * Vntagrefs(vg) + 1);
if(NULL == dimension)
{
/* replace it with NCadvice or HERROR?? */
#ifdef DEBUG
fprintf(stderr, "Out of memory line %d file %s\n", __LINE__, __FILE__);
#endif
ret_value = FAIL;
goto done;
}
/*
* Look through for a Vgroup of class _HDF_DIMENSION
*/
while((id = Vgetnext(vg, id)) != FAIL)
{
if(Visvg(vg, id))
{
dim = Vattach(handle->hdf_file, id, "r");
if(dim == FAIL)
continue; /* why do we continue? does this failure here
not matter? -GV */
if (Vgetclass(dim, vgclass) == FAIL)
{
ret_value = FAIL;
goto done;
}
if(!HDstrcmp(vgclass, _HDF_DIMENSION)
|| !HDstrcmp(vgclass, _HDF_UDIMENSION))
{
int is_dimval, is_dimval01;
/* init both flags to FALSE */
is_dimval = FALSE;
is_dimval01 = FALSE;
if (Vinquire(dim, &entries, vgname) == FAIL)
{
ret_value = FAIL;
goto done;
}
/*
* look through for a Vdata of class DIM_VALS01 and/or DIM_VALS
* to get size
*/
sub_id = -1;
while(((sub_id = Vgetnext(dim, sub_id)) != FAIL) )
{
if(Visvs(dim, sub_id))
{
vs = VSattach(handle->hdf_file, sub_id, "r");
if(vs == FAIL)
{
ret_value = FAIL;
goto done;
}
if (VSgetclass(vs, vsclass) == FAIL)
{
ret_value = FAIL;
goto done;
}
if(!HDstrcmp(vsclass, DIM_VALS))
{
is_dimval = TRUE;
if (HDstrcmp(vgclass, _HDF_UDIMENSION)) /* not unlimited di
m */
{
if (VSQuerycount(vs, &dim_size) == FAIL)
{
ret_value = FAIL;
goto done;
}
}
}
if ((!HDstrcmp(vsclass, DIM_VALS01))
|| (!HDstrcmp(vgclass, _HDF_UDIMENSION)))
{ /* DIM_VALS && _HDF_UDIMENSION */
int32 val; /* needs a temp var since handle->numrecs */
/* may not be an int32 */
/*
The call to VSsetfields fails for the files created with the library
version 3.3r1. This call is not necessary since handle vs is
obtained by specifying class name.
Elena Pourmal 2/17/99
if (VSsetfields(vs, "Values") == FAIL)
{
ret_value = FAIL;
goto done;
}
*/
if (VSseek(vs, 0) == FAIL)
{
ret_value = FAIL;
goto done;
}
/*
* This is highly dangerous since there might be multiple
* unlimited dimensions
*/
if(VSread(vs, (uint8 *) &val, 1, FULL_INTERLACE) != 1)
{
ret_value = FAIL;
goto done;
}
if (!HDstrcmp(vgclass, _HDF_UDIMENSION))
{
dim_size = NC_UNLIMITED;
handle->numrecs = val;
}
else
dim_size = val;
} /* */
if (!HDstrcmp(vsclass, DIM_VALS01)) /* dimval01 */
is_dimval01 = TRUE;
if (VSdetach(vs) == FAIL)
{
ret_value = FAIL;
goto done;
}
/* Is it the second dim vs of a compatible dim? */
found = FALSE;
for (i = count-1; ((i >= 0) && (!found)); i--)
{
if (!HDstrcmp(vgname, dimension[i]->name->values) &&
(dim_size == dimension[i]->size)) {
/* vgname is the dim name. vgname may be diff from vsname */
if (is_dimval01 == TRUE && is_dimval == TRUE)
dimension[i]->dim00_compat = 1;
found = TRUE; /* the second vs */
}
} /* for */
if (!found)
{
dimension[count] = NC_new_dim(vgname, dim_size);
if(NULL == dimension[count])
{
#ifdef DEBUG
/* replace it with NCadvice or HERROR?? */
fprintf(stderr, "Can't create new dimension #%d\n", count);
#endif
ret_value = FAIL;
goto done;
} /* dimension[count] */
#if DEBUG
fprintf(stderr, "Dimension <%s> has size %d\n", vgname, dim_size);
#endif
if (!HDstrcmp(vsclass, DIM_VALS01)) /* dimvals01 only */
dimension[count]->dim00_compat = 0;
count++;
} /* found */
} /* is vs */
} /* while in dimension vg */
} /* is vg */
if (Vdetach(dim) == FAIL)
{
ret_value = FAIL;
goto done;
}
} /* while */
}
if(count)
{
handle->dims = NC_new_array(NC_DIMENSION, count, (Void *) dimension);
if (handle->dims == NULL)
{
ret_value = FAIL;
goto done;
}
}
else
handle->dims = NULL;
#if DEBUG
fprintf(stderr, "Created dimension array %d \n", handle->dims);
#endif
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
if (handle->dims != NULL)
{
NC_free_array(handle->dims);
handle->dims = NULL;
}
}
/* Normal cleanup */
if (dimension != NULL)
HDfree(dimension);
return ret_value;
} /* hdf_read_dims */
/******************************************************************************
NAME
hdf_num_attrs
DESCRIPTION
Determine number of attributes in vgroup i.e. of the SDS
RETURNS
returns number of attributes in vgroup if successful and FAIL
otherwise.
*******************************************************************************/
static intn
hdf_num_attrs(NC *handle,/* IN: handle to SDS */
int32 vg /* IN: ref of top Vgroup */)
{
int count = 0;
int t, n;
int32 vs, tag;
int32 id = -1;
char class[MAX_NC_CLASS] = "";
intn ret_value = FAIL;
#ifdef HDF_NUM_ATTRS
fprintf(stderr, "hdf_num_attrs: I've been called, handle->hdf_file = %d\n", handle->hdf_file);
#endif
n = Vntagrefs(vg);
if (n == FAIL)
{
#ifdef HDF_NUM_ATTRS
fprintf(stderr,"hdf_read_attrs: Vntagrefs failed \n");
#endif
ret_value = FAIL;
goto done;
}
#ifdef HDF_NUM_ATTRS
fprintf(stderr,"hdf_num_attrs: Vntagrefs returned =%d \n",n);
#endif
/*
* look through for a Vdata of class _HDF_ATTRIBUTE
*/
for (t = 0; t < n; t++)
{
if (Vgettagref(vg, t, &tag, &id) == FAIL)
{
ret_value = FAIL;
goto done;
}
if(tag == DFTAG_VH)
{
vs = VSattach(handle->hdf_file, id, "r");
if(vs == FAIL)
{
ret_value = FAIL;
goto done;
}
if (VSgetclass(vs, class) == FAIL)
{
ret_value = FAIL;
goto done;
}
if(!HDstrcmp(class, _HDF_ATTRIBUTE))
count++;
if (VSdetach(vs) == FAIL)
{
ret_value = FAIL;
goto done;
}
}
}
#ifdef HDF_NUM_ATTRS
fprintf(stderr, "hdf_num_attrs: number of attributes is %d \n", count);
#endif
ret_value = count;
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
return ret_value;
} /* hdf_num_attrs */
/* ----------------------------------------------------------------
** Read in all attributes of the current vg
** Return NULL if something goes wrong
** Return a pointer to the array of attributes if all goes well
*/
NC_array *
hdf_read_attrs(XDR *xdrs, NC *handle, int32 vg)
{
int count, t, n;
int32 vs, tag, id, vsize, attr_size, nt;
nc_type type;
char vsname[MAX_NC_NAME] = "";
char fields[100] = "" ;
char class[MAX_NC_CLASS] = "";
char *values = NULL;
NC_attr **attributes = NULL;
NC_array *Array = NULL;
NC_array *ret_value = NULL;
count = 0;
id = -1;
#if DEBUG
fprintf(stderr, "hdf_read_attrs I've been called, handle->hdf_file = %d\n", handle->hdf_file);
#endif
n = Vntagrefs(vg);
if (n == FAIL)
{
#ifdef HDF_READ_ATTRS
fprintf(stderr,"hdf_read_attrs: Vntagrefs failed \n");
#endif
ret_value = NULL;
goto done;
}
#ifdef HDF_READ_ATTRS
fprintf(stderr,"hdf_read_attrs: Vntagrefs returned =%d \n",n);
#endif
/*
* Allocate enough space in case everything is an attribute
*/
count = 0;
attributes = (NC_attr **) HDmalloc(sizeof(NC_attr *) * n + 1);
if(NULL == attributes)
{
/* replace it with NCAdvice or HERROR? */
#ifdef HDF_READ_ATTRS
fprintf(stderr, "Out of memory line %d file %s\n", __LINE__, __FILE__);
#endif
ret_value = NULL;
goto done;
}
/*
* look through for a Vdata of class _HDF_ATTRIBUTE
*/
for (t = 0; t < n; t++)
{
if (Vgettagref(vg, t, &tag, &id) == FAIL)
{
ret_value = NULL;
goto done;
}
if(tag == DFTAG_VH)
{
vs = VSattach(handle->hdf_file, id, "r");
if(vs == FAIL)
{
ret_value = NULL;
goto done;
}
if (VSgetclass(vs, class) == FAIL)
{
ret_value = NULL;
goto done;
}
if(!HDstrcmp(class, _HDF_ATTRIBUTE))
{
if (VSinquire(vs, &attr_size, NULL, fields, &vsize, vsname) == FAIL)
{
ret_value = NULL;
goto done;
}
if ((nt = VFfieldtype(vs, 0)) == FAIL)
{
ret_value = NULL;
goto done;
}
if ((type = hdf_unmap_type(nt)) == FAIL)
{
ret_value = NULL;
goto done;
}
values = (char *) HDmalloc(vsize * attr_size + 1);
if (NULL == values)
{
ret_value = NULL;
goto done;
}
if (VSsetfields(vs, fields) == FAIL)
{
ret_value = NULL;
goto done;
}
if (VSread(vs, (uint8 *) values, attr_size, FULL_INTERLACE) == FAIL)
{
ret_value = NULL;
goto done;
}
if(type == NC_CHAR)
{
if ((attr_size = VFfieldorder(vs, 0)) == FAIL)
{
ret_value = NULL;
goto done;
}
((char *) values)[attr_size] = '\0';
}
attributes[count] =
(NC_attr *) NC_new_attr(vsname, type, attr_size, values);
if(NULL == attributes[count])
{
/* replace it with NCadvice or HERROR? */
#ifdef HDF_READ_ATTRS
fprintf(stderr, "hdf_read_attrs: Can't create new attribute #%d\n", count);
#endif
ret_value = NULL;
goto done;
}
attributes[count]->HDFtype = nt;
#ifdef HDF_READ_ATTRS
fprintf(stderr, "hdf_read_attrs: Attribute <%s> has type %d and size %d\n",
vsname, type, attr_size);
#endif
/* free values and reset to NULL */
HDfree(values);
values = NULL;
count++;
} /* end if attribute ? */
if (VSdetach(vs) == FAIL)
{
ret_value = NULL;
goto done;
}
} /* end if DFTAG_VH */
} /* end for */
/* create array of attributes */
if(count)
Array = NC_new_array(NC_ATTRIBUTE, count, (Void *) attributes);
#ifdef HDF_READ_ATTRS
fprintf(stderr, "hdf_read_attrs: Created attribute array %d \n", Array);
#endif
ret_value = Array; /* return array of attributes */
done:
if (ret_value == NULL)
{ /* Failure cleanup */
if (Array != NULL)
NC_free_array(Array);
}
/* Normal cleanup */
if (values != NULL)
HDfree(values);
if (attributes != NULL)
HDfree(attributes);
return ret_value;
} /* hdf_read_attrs */
/* ----------------------------------------------------------------
** Read in the variables out of a cdf structure
** Return FAIL if something goes wrong
**
** Important: We must already assume that handle->dims is set
** so that we can do a call to NC_var_shape() so that we can
** set the numrecs fields of variables (so we can fill record
** variables intelligently)
*/
intn
hdf_read_vars(XDR *xdrs,
NC *handle,
int32 vg)
{
char vgname[MAX_NC_NAME] = "";
char subname[MAX_NC_NAME] = "";
char class[MAX_NC_CLASS] = "";
NC_var **variables = NULL;
NC_var *vp = NULL;
int ndims, *dims = NULL;
uint8 ntstring[4];
int data_ref, is_rec_var, vg_size, count;
int32 data_count;
int32 HDFtype = FAIL;
int32 tag;
int32 id;
int32 n;
int32 sub_id;
int32 entries;
int32 ndg_ref = 0;
int32 rag_ref = 0;
intn nattrs;
register int t, i;
register nc_type type;
register int32 var, sub;
intn ret_value = SUCCEED;
#ifdef LATER
CONSTR(FUNC,"hdf_read_vars");
#endif /* LATER */
count = 0;
id = -1;
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars: I've been called, handle->hdf_file = %d\n", handle->hdf_file);
#endif
/*
* Allocate enough space in case everything is a variable
*/
count = 0;
variables = (NC_var **) HDmalloc(sizeof(NC_var *) * Vntagrefs(vg) + 1);
if(NULL == variables)
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Out of memory line %d file %s\n", __LINE__, __FILE__);
#endif
ret_value = FAIL;
goto done;
}
/*
* Allocate enough space in case lots of dimensions
*/
dims = (int *) HDmalloc(sizeof(int) * Vntagrefs(vg) + 1);
if(NULL == dims)
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Out of memory line %d file %s\n", __LINE__, __FILE__);
#endif
ret_value = FAIL;
goto done;
}
/*
* Look through for a Vgroup of class _HDF_VARIABLE
*/
if ((vg_size = Vntagrefs(vg)) == FAIL)
{
ret_value = FAIL;
goto done;
}
for(i = 0; i < vg_size; i++)
{
if (Vgettagref(vg, i, &tag, &id) == FAIL)
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Vgettagref failed\n");
#endif
ret_value = FAIL;
goto done;
}
if(tag == DFTAG_VG)
{
var = Vattach(handle->hdf_file, id, "r");
if(var == FAIL)
continue; /* isn't this bad? -GV */
if (Vgetclass(var, class) == FAIL)
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Vgetclass failed\n");
#endif
ret_value = FAIL;
goto done;
}
if(!HDstrcmp(class, _HDF_VARIABLE))
{
/*
* We have found a VGroup representing a Variable
*/
ndims = 0;
type = NC_UNSPECIFIED;
data_ref = 0;
data_count = 0;
rag_ref = 0;
is_rec_var = FALSE;
if (Vinquire(var, &n, vgname) == FAIL)
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Vinquire failed\n");
#endif
ret_value = FAIL;
goto done;
}
/*
* Loop through contents looking for dimensions
*/
for (t = 0; t < n; t++)
{
if (Vgettagref(var, t, &tag, &sub_id) == FAIL)
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Vgettagref failed\n");
#endif
ret_value = FAIL;
goto done;
}
switch(tag)
{
case DFTAG_VG : /* ------ V G R O U P ---------- */
sub = Vattach(handle->hdf_file, sub_id, "r");
if (FAIL == sub)
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Vattach failed\n");
#endif
ret_value = FAIL;
goto done;
}
if (FAIL == Vgetclass(sub, class))
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Vgetclass failed\n");
#endif
ret_value = FAIL;
goto done;
}
if(!HDstrcmp(class, _HDF_DIMENSION)
|| !HDstrcmp(class, _HDF_UDIMENSION))
{
if(!HDstrcmp(class, _HDF_UDIMENSION))
is_rec_var = TRUE;
if (FAIL == Vinquire(sub, &entries, subname))
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Vinquire failed\n");
#endif
ret_value = FAIL;
goto done;
}
dims[ndims] = (int) NC_dimid( handle, subname);
if (-1 == dims[ndims]) /* should change to FAIL */
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:NC_dimid failed\n");
#endif
ret_value = FAIL;
goto done;
}
ndims++;
}
if (FAIL == Vdetach(sub))
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Vdetach failed\n");
#endif
ret_value = FAIL;
goto done;
}
break;
case DFTAG_VH : /* ----- V D A T A ----- */
break;
case DFTAG_NDG : /* ----- NDG Tag for HDF 3.2 ----- */
ndg_ref = sub_id;
break;
case DFTAG_SD : /* ------- Data Storage ------ */
data_ref = sub_id;
/* Note: apparently Hlength will fail in certain cases, but
but this okay since I believe this is because
the data does not exist yet in the file?
So we can't catch this error -GV*/
data_count = Hlength(handle->hdf_file, DATA_TAG, sub_id);
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Hlength returned %d\n",data_count);
#endif
break;
case DFTAG_SDRAG : /* ----- Ragged Array index ----- */
rag_ref = sub_id;
#ifdef HDF_READ_VARS
printf("hdf_read_vars:Lookout! Found a ragged array element\n");
#endif
break;
case DFTAG_NT : /* ------- Number type ------- */
if(Hgetelement(handle->hdf_file, tag, sub_id, ntstring) == FAIL)
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Hgetlement failed\n");
#endif
ret_value = FAIL;
goto done;
}
HDFtype = ntstring[1];
if ((type = hdf_unmap_type(HDFtype)) == FAIL)
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:hdf_unmap_teyp failed\n");
#endif
ret_value = FAIL;
goto done;
}
/*
* Check if data was stored in native format
* And make sure the numbertype version numbers are the same
*/
if((ntstring[0] != DFNT_VERSION)
|| ((ntstring[3] != DFNTF_NONE)
&& (ntstring[3] != DFNTF_IEEE)))
{
/* check if in native mode for a different type of machine or external data file is LITEND */
if (ntstring[3] == DFNTF_PC)
HDFtype |= DFNT_LITEND;
else
{
if(ntstring[3] != (uint8)DFKgetPNSC(HDFtype, DF_MT))
{
/*
* OK, we have a problem here --- is in native mode
* for a different machine. PUNT
*/
goto bad_number_type; /* GOTO */
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars: BAD number type \n");
#endif
}
else
{
/*
* Is in native mode but its OK --- same machine type
*/
HDFtype |= DFNT_NATIVE;
}
}
}
break;
default:
/* Do nothing */
break;
}
}
variables[count] = NC_new_var(vgname, type, ndims, dims);
/* BMR: put back hdf type that was set wrong by
NC_new_var; please refer to the cvs history of
bug #172 for reason on this statement - 4/17/2001
*/
variables[count]->HDFtype = HDFtype;
vp = variables[count];
if(NULL == vp)
{
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:Can't read new variable %s\n", vgname);
#endif
ret_value = FAIL;
goto done;
}
#ifdef HDF_READ_VARS
fprintf(stderr,"hdf_read_vars:Created a variable called %s (id %d) \n", vgname, id);
#endif
/* Read in the attributes if any */
if ((nattrs = hdf_num_attrs(handle, var)) > 0)
vp->attrs = hdf_read_attrs(xdrs, handle, var);
else
vp->attrs = NULL;
#ifdef HDF_READ_VARS
fprintf(stderr,"hdf_read_vars:read in %d attributes \n",nattrs );
#endif
/* set up for easy access later */
vp->vgid = id;
vp->data_ref = data_ref;
vp->data_tag = DATA_TAG;
vp->HDFtype = HDFtype;
vp->ndg_ref = (uint16) ndg_ref;
vp->cdf = handle; /* for NC_var_shape */
/* need to process the ragged array info here */
/* QUESTION: Load the whole rag_fill list in now??????? */
if(rag_ref)
{
vp->is_ragged = TRUE;
}
if(vp->data_ref)
{
/*
* We have already seen data for this variable so now
* we need to worry about its numrecs field
*/
if(is_rec_var)
{
/*
* Call NC_var_shape() so we can figure out how many
* records have been written. This is horribly
* inefficient, but the separation-of-powers gets
* really mucked up if we wait till later...
*/
if(NC_var_shape(vp, handle->dims) == -1)
{
#ifdef HDF_READ_VARS
fprintf(stderr,"hdf_read_vars:NC_var_shape failed \n" );
#endif
ret_value = FAIL;
goto done;
}
/*
* Now figure out how many recs have been written
* For a while there was a -1 at the end of this
* equation. I don't remember why its there
* (4-Nov-93)
*/
vp->numrecs = data_count / vp->dsizes[0];
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars:I have set numrecs to %d\n", vp->numrecs);
#endif
/*
* Deallocate the shape info as it will be recomputed
* at a higher level later
*/
if(vp->shape != NULL)
HDfree(vp->shape);
if(vp->dsizes != NULL)
HDfree(vp->dsizes);
/* Reset these two pointers to NULL after
freeing. BMR 4/11/01 */
vp->shape = NULL;
vp->dsizes = NULL;
}
else
{
/* Not a rec var, don't worry about it */
vp->numrecs = 1;
}
} /* end vp->data_ref */
count++;
} /* end if vgroup class is variable */
bad_number_type: /* ? */
if (FAIL == Vdetach(var))
{
ret_value = FAIL;
goto done;
}
} /* end if DTAG_VG */
} /* end for vg_size */
/* create array of variables */
if(count)
{
handle->vars = NC_new_array(NC_VARIABLE, count, (Void *) variables);
if (NULL == handle->vars)
{
ret_value = FAIL;
goto done;
}
}
else
handle->vars = NULL;
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars: Created variable array %d \n", handle->vars);
#endif
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
#ifdef HDF_READ_VARS
fprintf(stderr, "hdf_read_vars: failed to created variable array \n");
#endif
if (handle->vars != NULL)
NC_free_array(handle->vars);
}
/* Normal cleanup */
if (variables != NULL)
HDfree(variables);
if (dims != NULL)
HDfree(dims);
return ret_value;
} /* hdf_read_vars */
/* ----------------------------------------------------------------
** Read in a cdf structure
*/
intn
hdf_read_xdr_cdf(xdrs, handlep)
XDR *xdrs;
NC **handlep;
{
#if DEBUG
char vgname[MAX_NC_NAME];
int32 entries;
#endif
register int32 cdf_vg = FAIL;
register int vgid = 0;
int status;
#ifdef OLD_WAY
register int found;
char class[MAX_NC_CLASS];
#endif /* OLD_WAY */
CONSTR(FUNC,"hdf_read_xdr_cdf");
intn ret_value = SUCCEED;
#if DEBUG
fprintf(stderr, "hdf_read_xdr_cdf i've been called %d\n", (*handlep)->hdf_file);
#endif
#ifdef OLD_WAY
/* find first thing of type _HDF_CDF */
vgid = -1;
found = FALSE;
while(!found
&& ((vgid = Vgetid((*handlep)->hdf_file, vgid)) != FAIL))
{
cdf_vg = Vattach((*handlep)->hdf_file, vgid, "r");
if(cdf_vg == FAIL)
{
HERROR(DFE_CANTATTACH);
ret_value = FAIL;
goto done;
}
if (Vgetclass(cdf_vg, class) == FAIL)
{
ret_value = FAIl;
goto done;
}
if(!HDstrcmp(class, _HDF_CDF))
found = TRUE;
else
{
if (Vdetach(cdf_vg) == FAIL)
{
ret_value = FAIL;
goto done;
}
}
}
if(!found)
{
ret_value = FAIL;
goto done;
}
#else /* new way */
if((vgid = Vfindclass((*handlep)->hdf_file,_HDF_CDF))!=FAIL)
{
cdf_vg = Vattach((*handlep)->hdf_file, vgid, "r");
if(cdf_vg == FAIL)
{
HERROR(DFE_CANTATTACH);
ret_value = FAIL;
goto done;
}
} /* end if */
else
{
ret_value = FAIL;
goto done;
}
#endif /* new way */
(*handlep)->vgid = vgid; /* ref of vgroup */
#if DEBUG
Vinquire(cdf_vg, &entries, vgname);
fprintf(stderr, "Found _HDF_CDF : %s (%d entries)\n", vgname, entries);
#endif
/* read in dimensions */
status = hdf_read_dims(xdrs, (*handlep), cdf_vg);
if(status == FAIL)
{
ret_value = FAIL;
goto done;
}
/* read in variables */
status = hdf_read_vars(xdrs, (*handlep), cdf_vg);
if(status == FAIL)
{
ret_value = FAIL;
goto done;
}
/* read in attributes */
if(hdf_num_attrs((*handlep), cdf_vg) > 0 )
(*handlep)->attrs = hdf_read_attrs(xdrs, (*handlep), cdf_vg);
else
(*handlep)->attrs = NULL;
/* deatch from cdf vgroup */
if (FAIL == Vdetach(cdf_vg))
{
ret_value = FAIL;
goto done;
}
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
if (cdf_vg != FAIL)
Vdetach(cdf_vg);
}
/* Normal cleanup */
return ret_value;
} /* hdf_read_xdr_cdf */
/* -------------------------------------------------------------------
** Read or write a CDF structure
**
** If we are reading, first try to read the information out of netCDF
** object stored explicitly in HDF files as netCDF objects. If
** that fails try to read SDSs out of the HDF file and interpret
** them as netCDF information.
*/
intn
hdf_xdr_cdf(xdrs, handlep)
XDR *xdrs;
NC **handlep;
{
CONSTR(FUNC,"hdf_xdr_cdf"); /* for HERROR */
intn status;
intn ret_value = SUCCEED;
#ifdef HDF_XDR_CDF
fprintf(stderr, "hdf_xdr_cdf: i've been called op = %d \n", xdrs->x_op);
#endif
switch(xdrs->x_op)
{
case XDR_ENCODE :
if((*handlep)->vgid)
{
if (FAIL == hdf_cdf_clobber((*handlep)))
{
ret_value = FAIL;
goto done;
}
}
status = hdf_write_xdr_cdf(xdrs, handlep);
if (FAIL == status)
{
#ifdef HDF_XDR_CDF
fprintf(stderr, "hdf_xdr_cdf: hdf_write_xdr_cdf failed \n");
#endif
ret_value = FAIL;
goto done;
}
break;
case XDR_DECODE :
if(FAIL == (status = hdf_read_xdr_cdf(xdrs, handlep)))
{
#ifdef HDF_XDR_CDF
fprintf(stderr, "hdf_xdr_cdf: hdf_read_xdr_cdf failed \n");
fprintf(stderr," going to hdf_read_sds \n");
#endif
status = hdf_read_sds_cdf(xdrs, handlep);
if(FAIL == status)
{
#ifdef HDF_XDR_CDF
fprintf(stderr, "hdf_xdr_cdf: hdf_read_sds failed \n");
#endif
HERROR(DFE_BADNDG);
ret_value = FAIL;
goto done;
}
} /* end if */
break;
case XDR_FREE :
if (FAIL == NC_free_cdf((*handlep)))
ret_value = FAIL;
else
ret_value = SUCCEED;
break;
default:
ret_value = FAIL;
}
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
return ret_value;
} /* hdf_xdr_cdf */
/* ---------------------- hdf_vg_clobber --------------- */
/*
Delete a VGroup that is on the disk. Basically, we will want to
just trash everything inside of it, making sure that any VDatas
with class == DATA are saved
*/
intn
hdf_vg_clobber(handle, id)
NC *handle;
int id;
{
int t, n;
int32 vg, tag, ref;
int32 status;
intn ret_value = SUCCEED;
#ifdef HDF_VG_CLOBBER
fprintf(stderr, "hdf_vg_clobber: has been called for vgroup ref=%d\n",id);
#endif
/* loop through and Clobber all top level VGroups */
/* attach to top level vgroup with read access */
vg = Vattach(handle->hdf_file, id, "r");
if(FAIL == vg)
{
#ifdef HDF_VG_CLOBBER
fprintf(stderr,"hdf_vg_clobber: Vattach failed for vgroup ref =%d\n",id);
HEprint(stderr,0);
#endif
ret_value = FAIL;
goto done;
}
/* get number of members in vgroup */
n = Vntagrefs(vg);
if (FAIL == n)
{
#ifdef HDF_VG_CLOBBER
fprintf(stderr,"hdf_vg_clobber: Vntagrefs failed \n");
#endif
ret_value = FAIL;
goto done;
}
/* Loop though and kill stuff */
for (t = 0; t < n; t++)
{ /* get tag/ref of elment in vgroup */
if (FAIL == Vgettagref(vg, t, &tag, &ref))
{
#ifdef HDF_VG_CLOBBER
fprintf(stderr,"hdf_vg_clobber: Vgettagref failed \n");
#endif
ret_value = FAIL;
goto done;
}
#ifdef HDF_VG_CLOBBER
fprintf(stderr, "hdf_vg_clobber: Looking at <%d, %d> in vgroup\n", tag, ref);
#endif
/* switch on the type of element: vgroup, vdata, data,
everyting else */
switch(tag)
{
case DFTAG_VG : /* recursive call */
#ifdef HDF_VG_CLOBBER
fprintf(stderr,"hdf_vg_clobber: found a vgroup ref %d in vgroup %d\n",ref,id);
#endif
/* check if vgroup exists in file before trying to delete
it's members */
if (vexistvg(handle->hdf_file, ref) != FAIL)
{
if (FAIL == hdf_vg_clobber(handle, ref))
{
#ifdef HDF_VG_CLOBBER
fprintf(stderr,"hdf_vg_clobber: hdf_vg_clobber failed member whose vgroup ref=%d\n",ref);
#endif
ret_value = FAIL;
goto done;
}
}
break;
case DFTAG_VH :
/* check if vdata exists in file before trying to delete it */
if (vexistvs(handle->hdf_file, ref) != FAIL)
{
status = VSdelete(handle->hdf_file, (int32) ref);
if (FAIL == status)
{
#ifdef HDF_VG_CLOBBER
fprintf(stderr,"hdf_vg_clobber: VSdelete failed for vdata ref=%d\n",ref);
#endif
ret_value = FAIL;
goto done;
}
}
#ifdef HDF_VG_CLOBBER
fprintf(stderr,"hdf_vg_clobber: VSdelete deleted vdata ref=%d\n",ref);
#endif
break;
case DFTAG_SD :
/*
* Don't delete actual numeric data
* I guess this means we save it? -GV
*/
break;
default: /* delete other objects given tag/ref in file */
if (FAIL == Hdeldd(handle->hdf_file, (uint16) tag, (uint16) ref))
{
#ifdef HDF_VG_CLOBBER
fprintf(stderr,"hdf_vg_clobber: Hdeldd failed \n");
#endif
ret_value = FAIL;
goto done;
}
#ifdef HDF_VG_CLOBBER
fprintf(stderr,"hdf_vg_clobber: Hdeldd deleted tag/ref=%d/%d\n",tag,ref);
#endif
break;
}
}
ret_value = Vdetach(vg);
#ifdef HDF_VG_CLOBBER
fprintf(stderr, "hdf_vg_clobber: Vdetach, ret_value=%d \n",ret_value);
#endif
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
#ifdef HDF_VG_CLOBBER
fprintf(stderr, "hdf_vg_clobber: failed \n");
#endif
}
/* Normal cleanup */
return ret_value;
} /* hdf_vg_clobber */
/* --------------------------- hdf_cdf_clobber ---------------------------- */
/*
Delete a netCDF structure that has been already written to disk
*/
intn
hdf_cdf_clobber(handle)
NC *handle;
{
int32 vg, tag, ref;
int n, t, status;
intn ret_value = SUCCEED;
if(!handle->vgid)
{ /* okay right? */
ret_value = SUCCEED; /* hmm...since ref of vgroup is zero? */
goto done;
}
/* Close open VData pointers */
if (FAIL == hdf_close(handle))
{
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: hdf_close failed \n");
#endif
ret_value = FAIL;
goto done;
}
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: closed all open vdata handles \n");
#endif
/* loop through and Clobber all top level VGroups */
vg = Vattach(handle->hdf_file, handle->vgid, "r");
if(vg == FAIL)
{
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: Vattach failed for vgroup ref=%d\n",
handle->vgid);
#endif
ret_value = FAIL;
goto done;
}
/* get number of members of Vgroup */
n = Vntagrefs(vg);
if (FAIL == n)
{
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: Vntagrefs failed \n");
#endif
ret_value = FAIL;
goto done;
}
/* Loop though and just kill everyone */
for (t = 0; t < n; t++)
{
if (FAIL == Vgettagref(vg, t, &tag, &ref))
{
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: Vgettagref failed for vgroup %d\n",
handle->vgid);
#endif
ret_value = FAIL;
goto done;
}
/* if this member is a vgroup destroy everything in it */
if(tag == DFTAG_VG)
{
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: member of vgroup is a vgroup,");
fprintf(stderr,"deleteing everything in vgroup %d \n",ref);
#endif
/* check if vgroup exists in file */
if (vexistvg(handle->hdf_file, ref) != FAIL)
{
hdf_vg_clobber(handle, ref);
}
}
switch(tag)
{
case DFTAG_VG:
status = Vdelete(handle->hdf_file, (int32) ref);
if (FAIL == status)
{
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: Vdelete failed for vgroup %d\n",
ref);
#endif
ret_value = FAIL;
goto done;
}
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: Vdelete deleted vgroup %d\n",
ref);
#endif
break;
case DFTAG_VH:
status = VSdelete(handle->hdf_file, (int32) ref);
if (FAIL == status)
{
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: VSdelete failed for vdata %d\n",
ref);
#endif
ret_value = FAIL;
goto done;
}
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: VSdelete deleted vdata %d\n",
ref);
#endif
break;
default:
status = Hdeldd(handle->hdf_file, (uint16) tag, (uint16) ref);
if (FAIL == status)
{
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: Hdeldd failed for tag/ref %d/%d\n",
tag,ref);
#endif
ret_value = FAIL;
goto done;
}
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: Hdeldd deleted tag/ref %d/%d\n",
tag,ref);
#endif
break;
} /* end switch tag */
}/* end for every member in vgroup */
if (FAIL == Vdetach(vg))
{
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: Vdetach failed for vgroup %d\n",
handle->vgid);
#endif
ret_value = FAIL;
goto done;
}
status = Vdelete(handle->hdf_file, (int32) handle->vgid);
if (FAIL == status)
{
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: Vdelete failed for vgroup %d\n",
handle->vgid);
#endif
ret_value = FAIL;
goto done;
}
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber:Clobbering VGroup %d\n\n", handle->vgid);
#endif
handle->vgid = 0; /* reset ref of SDS vgroup to invalid ref */
done:
if(ret_value == FAIL)
{ /* Error condition cleanup */
#ifdef HDF_CDF_CLOBBER
fprintf(stderr,"hdf_cdf_clobber: Failed to Clobber VGroup %d\n\n", handle->vgid);
#endif
} /* end if */
/* Normal function cleanup */
return ret_value;
} /* hdf_cdf_clobber */
/* -------------------------- hdf_close --------------------- */
/*
We're about to close the file, do last minute HDF cleanup
Also dump the number of records currently instatiated into the
unlimited dimensions.
BUG: All unlimited dimensions will have the same size
*/
intn
hdf_close(handle)
NC *handle;
{
NC_array *tmp = NULL;
NC_var **vp = NULL;
Void *vars = NULL;
register int i;
int id, sub_id;
int32 vg, dim;
int32 vs;
char class[MAX_NC_CLASS] = "";
intn ret_value = SUCCEED;
#ifdef LATER
CONSTR(FUNC,"hdf_close");
#endif /* LATER */
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: I've been called\n");
#endif
/* loop through and detach from variable data VDatas */
if(handle->vars)
{
tmp = handle->vars;
vars = handle->vars->values;
for(i = 0; i < tmp->count; i++)
{
vp = (NC_var **) vars;
if((*vp)->aid != FAIL)
{
if (FAIL == Hendaccess((*vp)->aid))
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: Hendaccess failed for vdata aid %d\n",
(*vp)->aid);
#endif
ret_value = FAIL;
goto done;
}
}
(*vp)->aid = FAIL; /* reset access id */
vars += tmp->szof;
} /* end for each variable */
}
/* loop through top level looking for unlimited dimensions.
we write them out? -GV */
if(handle->flags & NC_NDIRTY)
{
id = -1;
vg = Vattach(handle->hdf_file, handle->vgid, "r");
if (FAIL == vg)
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: Vattach failed for vgroup ref %d\n",
handle->vgid);
#endif
ret_value = FAIL;
goto done;
}
/* go through vgroup hierachy */
while((id = Vgetnext(vg, id)) != FAIL)
{
if(Visvg(vg, id))
{
dim = Vattach(handle->hdf_file, id, "r");
if (FAIL == dim)
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: Vattach failed for vgroup ref %d\n",
id);
#endif
ret_value = FAIL;
goto done;
}
if (FAIL == Vgetclass(dim, class))
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: Vgetclass failed for vgroup ref %d\n",
id);
#endif
ret_value = FAIL;
goto done;
}
/* look for proper vgroup */
if(!HDstrcmp(class, _HDF_UDIMENSION))
{
sub_id = -1;
/* look for vdata in vgroup */
while((sub_id = Vgetnext(dim, sub_id)) != FAIL)
{
if(Visvs(dim, sub_id))
{ /* yes, attach to vdata */
vs = VSattach(handle->hdf_file, sub_id, "w");
if(vs == FAIL)
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: VSattach failed for vdata ref %d\n",
sub_id);
#endif
ret_value = FAIL;
goto done;
/* HEprint(stdout, 0); */
}
/* get class of vdata */
if (FAIL == VSgetclass(vs, class))
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: VSgetclass failed for vdata ref %d\n",
sub_id);
#endif
ret_value = FAIL;
goto done;
}
/* are these dimension vdatas? */
if(!HDstrcmp(class, DIM_VALS)
|| !HDstrcmp(class, DIM_VALS01))
{ /* yes */
int32 val = handle->numrecs;
if (FAIL == VSsetfields(vs, "Values"))
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: VSsetfields failed for vdata ref %d\n",
sub_id);
#endif
ret_value = FAIL;
goto done;
}
if (FAIL == VSseek(vs, 0))
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: VSseek failed for vdata ref %d\n",
sub_id);
#endif
ret_value = FAIL;
goto done;
}
/* write out dimension vdatas? */
if(VSwrite(vs, (uint8 *)&val, 1, FULL_INTERLACE) != 1)
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: VSwrite failed for vdata ref %d\n",
sub_id);
#endif
ret_value = FAIL;
goto done;
}
}
/* detach from vdata */
if (FAIL == VSdetach(vs))
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: VSdetach failed for vdata ref %d\n",
sub_id);
#endif
ret_value = FAIL;
goto done;
}
} /* end if vdata */
} /* end while looking for vdata in vgroup */
} /* end if UNLIMTED dimension vgroup */
if (FAIL == Vdetach(dim))
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: Vdetach failed for vgroup ref %d\n",
id);
#endif
ret_value = FAIL;
goto done;
}
}/* end if vgroup */
} /* end if looking through toplevel vgroup hierachy */
if (FAIL == Vdetach(vg))
{
#ifdef HDF_CLOSE
fprintf(stderr,"hdf_close: Vdetach failed for vgroup ref %d\n",
handle->vgid);
#endif
ret_value = FAIL;
goto done;
}
} /* end if we need to flush out unlimited dimensions? */
#ifdef QAK
/* Free dimension array if necessary */
if(handle->dims)
NC_free_array(handle->dims); /* Might need to close Vdatas? -QAK */
#endif /* QAK */
done:
if(ret_value == FAIL)
{ /* Error condition cleanup */
} /* end if */
/* Normal function cleanup */
return ret_value;
} /* hdf_close */
/*******************************************************************************/
#endif /* HDF */
/*
* How much space will the xdr'd NC description take.
*
*/
int NC_xlen_cdf(cdf)
NC *cdf ;
{
int len = 8 ;
if(cdf == NULL)
return(0) ;
len += NC_xlen_array(cdf->dims) ;
len += NC_xlen_array(cdf->attrs) ;
len += NC_xlen_array(cdf->vars) ;
return(len) ;
}
#define RECPOS 4L /* seek index of numrecs value */
bool_t
xdr_numrecs(xdrs, handle)
XDR *xdrs;
NC *handle;
{
#ifdef HDF
if(handle->file_type == HDF_FILE)
return TRUE; /* hmm...why? */
#endif
if( (handle->flags & NC_NOFILL)
&& xdrs->x_op == XDR_ENCODE
&& handle->begin_rec > 0)
{
/*
* we need to write something just beyond the last
* record so we can successfully read back the
* entire last record.
*/
if( !xdr_setpos(xdrs, handle->begin_rec
+ handle->numrecs * handle->recsize) )
{
nc_serror("Can't set position to EOF") ;
return(FALSE) ;
}
#ifdef RDEBUG
fprintf(stderr,"\txdr_numrecs %ld = %d + %ld * %d\n",
xdr_getpos(xdrs),
handle->begin_rec, handle->numrecs, handle->recsize) ;
#endif /* RDEBUG */
if( !xdr_u_long(xdrs, &(handle->numrecs)) )
return(FALSE) ;
}
if( !xdr_setpos(xdrs, RECPOS) )
{
nc_serror("Can't set position to RECPOS") ;
return(FALSE) ;
}
return( xdr_u_long(xdrs, &(handle->numrecs)) ) ;
}
static bool_t
xdr_4bytes(xdrs, cp)
XDR *xdrs ;
char *cp ; /* at least 4 valid bytes */
{
return xdr_opaque(xdrs, cp, 4) ;
}
static bool_t
xdr_2shorts(xdrs, sp)
XDR *xdrs ;
short *sp ; /* at least 2 valid shorts */
{
return xdr_shorts(xdrs, sp, 2) ;
}
bool_t
xdr_NC_fill(xdrs, vp)
XDR *xdrs ;
NC_var *vp ;
{
char fillp[2*sizeof(double)] ;
bool_t stat ;
bool_t (*xdr_NC_fnct)() ;
u_long alen = vp->len ;
NC_attr **attr = NULL ;
/*
* set up fill value
*/
/* start with the default */
NC_arrayfill((Void *)fillp, (size_t)2*sizeof(double),
vp->type) ;
/*
* if there is a valid user defined value, use it instead
*/
attr = NC_findattr(&vp->attrs, _FillValue) ;
if( attr != NULL )
{
if( (*attr)->data->type != vp->type || (*attr)->data->count != 1 )
NCadvise(NC_EBADTYPE, "var %s: _FillValue type mismatch",
vp->name->values) ;
else
{
int len = NC_typelen(vp->type) ;
char *cp = fillp ;
while(cp < &fillp[sizeof(fillp) -1])
{
NC_copy_arrayvals(cp, (*attr)->data) ;
cp += len ;
}
}
}
switch(vp->type){
case NC_BYTE :
case NC_CHAR :
alen /= 4 ;
xdr_NC_fnct = xdr_4bytes ;
break ;
case NC_SHORT :
alen /= 4 ;
xdr_NC_fnct = xdr_2shorts ;
break ;
case NC_LONG :
alen /= 4 ;
#if defined _CRAYMPP
xdr_NC_fnct = xdr_short;
#elif defined __alpha || (_MIPS_SZLONG == 64) || defined __ia64 || (defined __sun && defined _LP64) || defined AIX5L64 || defined __x86_64__
xdr_NC_fnct = xdr_int ;
#else
xdr_NC_fnct = xdr_long ;
#endif
break ;
case NC_FLOAT :
alen /= 4 ;
xdr_NC_fnct = xdr_float ;
break ;
case NC_DOUBLE :
alen /= 8 ;
xdr_NC_fnct = xdr_double ;
break ;
default :
NCadvise(NC_EBADTYPE, "bad type %d", vp->type) ;
return(FALSE) ;
}
/* write out fill values */
for(stat = TRUE ; stat && (alen > 0) ; alen--)
{
stat = (*xdr_NC_fnct)(xdrs,fillp) ;
}
if(!stat)
{
NCadvise(NC_EXDR, "xdr_NC_fill") ;
return(FALSE) ;
}
return(TRUE) ;
}
syntax highlighted by Code2HTML, v. 0.9.1