/*
* Copyright 1993, University Corporation for Atmospheric Research
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
*/
/* $Id: array.c,v 1.19 2003/12/10 21:15:09 epourmal Exp $ */
#include <string.h>
#include "local_nc.h"
#include "alloc.h"
#ifdef NO_MEM_FUNCTS
/*
* internal replacement for memset
*/
char *
NCmemset (s, c, n)
char *s;
int c, n;
{
char *cp ;
for (cp = s ; cp < &s[n] ; *cp++ = c )
/* nada */ ;
return s ;
}
#endif
/*
* for a netcdf type
* return the size of the on-disk representation
*/
int
NC_xtypelen(type)
nc_type type ;
{
char *nada = NULL ;
switch(type){
case NC_BYTE :
case NC_CHAR :
return(1) ;
case NC_SHORT :
return(2) ;
case NC_LONG :
case NC_FLOAT :
return(4) ;
case NC_DOUBLE :
return(8) ;
/* private types */
case NC_UNSPECIFIED :
return(0) ;
case NC_STRING :
return(NC_xlen_string((NC_string *)NULL)) ;
case NC_DIMENSION :
return(NC_xlen_dim((NC_dim **)&nada)) ;
case NC_VARIABLE :
return(NC_xlen_var((NC_var **)&nada)) ;
case NC_ATTRIBUTE :
return(NC_xlen_attr((NC_attr **)&nada)) ;
default :
NCadvise(NC_EBADTYPE, "NC_xtypelen: Unknown type %d", type) ;
return(-1) ;
}
}
/*
* private version of nctypelen
*/
size_t
NC_typelen(type)
nc_type type ;
{
switch(type){
case NC_BYTE :
case NC_CHAR :
return(sizeof(char)) ;
case NC_SHORT :
return(sizeof(short)) ;
case NC_LONG :
return(sizeof(nclong)) ;
case NC_FLOAT :
return(sizeof(float)) ;
case NC_DOUBLE :
return(sizeof(double)) ;
/* private types */
case NC_STRING :
return(sizeof(NC_string *)) ;
case NC_DIMENSION :
return(sizeof(NC_dim *)) ;
case NC_VARIABLE :
return(sizeof(NC_var *)) ;
case NC_ATTRIBUTE :
return(sizeof(NC_attr *)) ;
default :
return(0) ;
}
}
/*
* external interface function
* this is how much space is required by the user, as in
*
* vals = malloc(nel * nctypelen(var.type));
* ncvarget (cdfid, varid, cor, edg, vals);
*
*/
int
nctypelen(type)
nc_type type ;
{
switch(type){
case NC_BYTE :
case NC_CHAR :
return(sizeof(char)) ;
case NC_SHORT :
return(sizeof(short)) ;
case NC_LONG :
return(sizeof(nclong)) ;
case NC_FLOAT :
return(sizeof(float)) ;
case NC_DOUBLE :
return(sizeof(double)) ;
default :
NCadvise(NC_EBADTYPE, "Unknown type %d", type) ;
return(-1) ;
}
}
/* See netcdf.h for explanation of these initialzations */
/* assert( !(USE_F_UNION && USE_F_LONG_PUN) ) ; */
/* assert( !(USE_D_UNION && USE_D_LONG_PUN) ) ; */
#ifdef USE_F_UNION
#ifndef SWAP
union xdr_f_union xdr_f_infs = {0x7f, 0x80, 0x00, 0x00} ;
#else
union xdr_f_union xdr_f_infs = {0x00, 0x00, 0x80, 0x7f} ;
#endif /* !SWAP */
#endif /* USE_F_UNION */
#ifdef USE_D_UNION
#ifndef SWAP
union xdr_d_union xdr_d_infs = {0x7f, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00} ;
#else
union xdr_d_union xdr_d_infs = {0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x7f} ;
#endif /* !SWAP */
#endif /* USE_D_UNION */
#ifdef USE_F_LONG_PUN
nclong xdr_f_infinity = 0x7f800000;
#endif
#ifdef USE_D_LONG_PUN
#ifndef SWAP
nclong xdr_d_infinity[2] = {0x7ff00000,0x00000000};
#else
nclong xdr_d_infinity[2] = {0x00000000,0x7ff00000};
#endif /* !SWAP */
#endif /* USE_D_LONG_PUN */
/*
* Fill an array region with an appropriate special value
*/
void
NC_arrayfill(low, len, type)
void *low ; /* lower bound of area to be filled */
size_t len ; /* how many bytes */
nc_type type ;
{
char *hi, *lo; /* local low and hi ptr */
lo = low;
hi = lo + len;
switch(type) {
case NC_BYTE :
HDmemset(lo, FILL_BYTE, len);
break ;
case NC_CHAR :
HDmemset(lo, FILL_CHAR, len);
break ;
case NC_SHORT :
while(lo < hi ){
*((short *)lo) = FILL_SHORT ;
lo += sizeof(short);
}
break ;
case NC_LONG :
while(lo < hi ){
*((nclong *)lo) = FILL_LONG ;
lo += sizeof(nclong) ;
}
break ;
case NC_FLOAT :
while(lo < hi ){
*((float *)lo) = FILL_FLOAT ;
lo += sizeof(float) ;
}
break ;
case NC_DOUBLE :
while(lo < hi ){
/*SUPPRESS 450*/
*((double *)lo) = FILL_DOUBLE ;
lo += sizeof(double) ;
}
break ;
default :
HDmemset(lo,0xff,len) ;
break ;
}
}
/*
* Allocate a new array, returning a handle to it, NULL on error.
* If count is no-zero, allocate private space for the values, and,
* if values is non-NULL, copy them in.
* Else, just hook up the values passed in.
*/
NC_array *
NC_new_array(type, count, values)
nc_type type ;
unsigned count ;
const void *values ;
{
NC_array *ret ;
size_t memlen ;
ret = (NC_array *)HDmalloc(sizeof(NC_array)) ;
if( ret == NULL )
goto alloc_err ;
ret->type = type ;
ret->szof = NC_typelen(type) ;
#ifdef DEBUG
fprintf(stderr, "NC_new_array(): type=%u, NC_typelen(type)=%u\n",(unsigned)type,(unsigned)ret->szof);
#endif
ret->count = count ;
memlen = count * ret->szof ;
ret->len = count * NC_xtypelen(type) ;
#ifdef DEBUG
fprintf(stderr, "NC_new_array(): count=%u, memlen=%u\n",count,memlen);
#endif
if( count != 0 )
{
ret->values = (Void*)HDmalloc(memlen) ;
#ifdef DEBUG
fprintf(stderr, "NC_new_array(): ret->values=%p, values=%p\n",ret->values,values);
#endif
if(ret->values == NULL)
goto alloc_err ;
if( values == NULL )
{
NC_arrayfill(ret->values, memlen, type) ;
} else {
/* can be dangerous */
(void)memcpy(ret->values, values, memlen) ;
}
} else {
ret->values = NULL ;
}
#ifdef DEBUG
fprintf(stderr, "NC_new_array(): ret=%p\n",ret);
#endif
return(ret) ;
alloc_err :
nc_serror("NC_new_array") ;
return(NULL) ;
}
/*
* Recyle a NC_array, if possible.
* EG, if there is enough space, use it, else return NULL
* If values is non-NULL, copy them in.
*/
NC_array *
NC_re_array(old, type, count, values)
NC_array *old ;
nc_type type ;
unsigned count ;
const void *values ;
{
size_t memlen ;
size_t szof ;
szof = NC_typelen(type) ;
memlen = count * szof ;
if(memlen > old->count * old->szof )
return(NULL) ; /* punt */
old->count = count ;
old->type = type ;
old->szof = szof ;
if(count != 0)
{
if( values == NULL )
{
NC_arrayfill(old->values, memlen, type) ;
} else {
/* can be dangerous */
(void)memcpy(old->values, values, memlen) ;
}
}
return(old) ;
}
/*
* Free array, and, if needed, its values.
*
* NOTE: Changed return value to return 'int'
* If successful returns SUCCEED else FAIL -GV 9/19/97
*/
int
NC_free_array(array)
NC_array *array ;
{
int ret_value = SUCCEED;
if( array != NULL)
{
if(array->values != NULL)
{
switch(array->type)
{
case NC_UNSPECIFIED :
case NC_BYTE :
case NC_CHAR :
case NC_SHORT :
case NC_LONG :
case NC_FLOAT :
case NC_DOUBLE :
break ;
case NC_STRING :
{
NC_string **sp ;
sp = (NC_string **)array->values ;
for(sp += array->count - 1 ;
array->count > 0;
array->count--)
{
if (FAIL == NC_free_string(*sp-- ))
{
ret_value = FAIL;
goto done;
}
}
}
break ;
case NC_DIMENSION :
{
NC_dim **dp ;
dp = (NC_dim**)array->values ;
for(dp += array->count - 1 ;
array->count > 0;
array->count--)
{
if (FAIL == NC_free_dim(*dp-- ))
{
ret_value = FAIL;
goto done;
}
}
}
break ;
case NC_VARIABLE :
{
NC_var **dp ;
dp = (NC_var**)array->values ;
for(dp += array->count - 1 ;
array->count > 0;
array->count--)
{
if (FAIL == NC_free_var(*dp-- ))
{
ret_value = FAIL;
goto done;
}
}
}
break ;
case NC_ATTRIBUTE :
{
NC_attr **dp ;
dp = (NC_attr**)array->values ;
for(dp += array->count - 1 ;
array->count > 0;
array->count--)
{
if (FAIL == NC_free_attr(*dp-- ))
{
ret_value = FAIL;
goto done;
}
}
}
break ;
default:
NCadvise(NC_EBADTYPE, "Unknown type %d",array->type) ;
break ;
}
Free(array->values) ;
}
Free(array) ;
}
done:
if (ret_value == FAIL)
{ /* Failure cleanup */
}
/* Normal cleanup */
return ret_value;
}
/*
* How much space will the xdr'd array take.
*/
int NC_xlen_array(array)
NC_array *array ;
{
int len = 8 ;
int rem ;
int (*xlen_funct)() =NULL;
Void *vp ;
int ii ;
if(array!=NULL)
{
switch(array->type){
case NC_BYTE :
case NC_CHAR :
len += array->count ;
if( (rem = len%4) != 0)
len += 4 - rem ;
return(len) ;
case NC_SHORT :
len += array->count * 2 ;
if( (rem = len%4) != 0)
len += 4 - rem ;
return(len) ;
case NC_LONG :
case NC_FLOAT :
len += array->count * 4 ;
return(len) ;
case NC_DOUBLE :
len += array->count * 8 ;
return(len) ;
case NC_STRING :
xlen_funct = NC_xlen_string ;
break ;
case NC_DIMENSION :
xlen_funct = NC_xlen_dim ;
break ;
case NC_VARIABLE :
xlen_funct = NC_xlen_var ;
break ;
case NC_ATTRIBUTE :
xlen_funct = NC_xlen_attr ;
break ;
default:
break;
}
vp = array->values ;
for(ii=0 ; ii < array->count ; ii++)
{
len += (*xlen_funct)(vp) ;
vp += array->szof ;
}
}
return(len) ;
}
/*
* Add a new handle on the end of and array of handles
*/
Void *
NC_incr_array(array, tail)
NC_array *array ;
Void *tail ;
{
char *ap ;
if(array == NULL)
{
NCadvise(NC_EINVAL, "increment: NULL array") ;
return(NULL) ;
}
array->values = (Void*)HDrealloc(array->values,
(array->count +1) * array->szof) ;
if(array->values == NULL)
{
nc_serror("extend_array") ;
return(NULL) ;
}
ap = array->values + array->szof * array->count ;
(void)memcpy(ap, tail, array->szof) ;
array->count ++ ;
return(array->values) ;
}
/*
* Definitely NOT Bomb proof.
*/
void
NC_copy_arrayvals( target, array )
char *target ;
NC_array *array ;
{
size_t memlen ;
memlen = array->szof * array->count ;
(void)memcpy(target, array->values, memlen) ;
}
bool_t
xdr_NC_array(xdrs, app)
XDR *xdrs;
NC_array **app;
{
bool_t (*xdr_NC_fnct)() ;
u_long count , *countp=NULL ;
nc_type type , *typep=NULL ;
bool_t stat ;
Void *vp ;
switch (xdrs->x_op) {
case XDR_FREE:
NC_free_array((*app)) ;
return(TRUE) ;
case XDR_ENCODE:
if(*app == NULL)
{
(*app) = NC_new_array(NC_UNSPECIFIED, (unsigned)0,
(Void*)NULL) ;
if(*app == NULL)
{
NCadvise(NC_EXDR, "xdr_NC_array:NC_new_array") ;
return(FALSE) ;
}
}
count = (*app)->count ;
type = (*app)->type ;
/* fall into */
case XDR_DECODE:
countp = &count ;
typep = &type ;
break ;
}
#ifdef USE_ENUM
if (! xdr_enum(xdrs, (enum_t *)typep)) {
NCadvise(NC_EXDR, "xdr_NC_array:xdr_enum") ;
return (FALSE);
}
#else
if (! xdr_int(xdrs, typep)) {
NCadvise(NC_EXDR, "xdr_NC_array:xdr_int (enum)") ;
return (FALSE);
}
#endif
if (! xdr_u_long(xdrs, countp)) {
NCadvise(NC_EXDR, "xdr_NC_array:xdr_u_long") ;
return (FALSE);
}
if( xdrs->x_op == XDR_DECODE )
{
if( *typep == NC_UNSPECIFIED && *countp == 0 )
{
*app = NULL ;
return(TRUE) ;
} /* else */
(*app) = NC_new_array(*typep, (unsigned)*countp, (Void*)NULL) ;
if((*app) == NULL)
{
NCadvise(NC_EXDR, "xdr_NC_array:NC_new_array (second call)") ;
return(FALSE) ;
}
}
vp = (*app)->values ;
switch(*typep){
case NC_UNSPECIFIED :
case NC_BYTE :
case NC_CHAR :
xdr_NC_fnct = xdr_opaque ;
goto func ;
case NC_SHORT :
xdr_NC_fnct = xdr_shorts ;
goto func ;
case NC_LONG :
#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
goto loop ;
case NC_FLOAT :
xdr_NC_fnct = xdr_float ;
goto loop ;
case NC_DOUBLE :
xdr_NC_fnct = xdr_double ;
goto loop ;
/* private types */
case NC_STRING :
xdr_NC_fnct = xdr_NC_string ;
goto loop ;
case NC_DIMENSION :
xdr_NC_fnct = xdr_NC_dim ;
goto loop ;
case NC_VARIABLE :
xdr_NC_fnct = xdr_NC_var ;
goto loop ;
case NC_ATTRIBUTE :
xdr_NC_fnct = xdr_NC_attr ;
goto loop ;
default :
{
NCadvise(NC_EBADTYPE, "xdr_NC_array: unknown type 0x%x", (unsigned)*typep) ;
return(FALSE) ;
}
}
loop:
for(stat = TRUE ; stat && (count > 0) ; count--)
{
stat = (*xdr_NC_fnct)(xdrs,vp) ;
vp += (*app)->szof ;
}
if ( !stat ) NCadvise(NC_EXDR, "xdr_NC_array: loop") ;
return(stat) ;
func:
stat = (*xdr_NC_fnct)(xdrs, vp, *countp);
if ( !stat ) NCadvise(NC_EXDR, "xdr_NC_array: func") ;
return( stat );
}
syntax highlighted by Code2HTML, v. 0.9.1