#line 5 "attr.m4"
/* Do not edit this file. It is produced from the corresponding .m4 source */
#line 7
/*
 *	Copyright 2018, University Corporation for Atmospheric Research
 *      See netcdf/COPYRIGHT file for copying and redistribution conditions.
 */

#if HAVE_CONFIG_H
#include <config.h>
#endif

#include "nc3internal.h"
#include "ncdispatch.h"
#include "nc3dispatch.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "ncx.h"
#include "fbits.h"
#include "rnd.h"
#include "ncutf8.h"

/*
 * Free attr
 * Formerly
NC_free_attr()
 */
void
free_NC_attr(NC_attr *attrp)
{

	if(attrp == NULL)
		return;
	free_NC_string(attrp->name);
	free(attrp);
}


/*
 * How much space will 'nelems' of 'type' take in
 *  external representation (as the values of an attribute)?
 */
static size_t
ncx_len_NC_attrV(nc_type type, size_t nelems)
{
	switch(type) {
	case NC_BYTE:
	case NC_CHAR:
		return ncx_len_char(nelems);
	case NC_SHORT:
		return ncx_len_short(nelems);
	case NC_INT:
		return ncx_len_int(nelems);
	case NC_FLOAT:
		return ncx_len_float(nelems);
	case NC_DOUBLE:
		return ncx_len_double(nelems);
	case NC_UBYTE:
		return ncx_len_ubyte(nelems);
	case NC_USHORT:
		return ncx_len_ushort(nelems);
	case NC_UINT:
		return ncx_len_uint(nelems);
	case NC_INT64:
		return ncx_len_int64(nelems);
	case NC_UINT64:
		return ncx_len_uint64(nelems);
	default:
	        assert("ncx_len_NC_attr bad type" == 0);
	}
	return 0;
}


NC_attr *
new_x_NC_attr(
	NC_string *strp,
	nc_type type,
	size_t nelems)
{
	NC_attr *attrp;
	const size_t xsz = ncx_len_NC_attrV(type, nelems);
	size_t sz = M_RNDUP(sizeof(NC_attr));

	assert(!(xsz == 0 && nelems != 0));

	sz += xsz;

	attrp = (NC_attr *) malloc(sz);
	if(attrp == NULL )
		return NULL;

	attrp->xsz = xsz;

	attrp->name = strp;
	attrp->type = type;
	attrp->nelems = nelems;
	if(xsz != 0)
		attrp->xvalue = (char *)attrp + M_RNDUP(sizeof(NC_attr));
	else
		attrp->xvalue = NULL;

	return(attrp);
}


/*
 * Formerly
NC_new_attr(name,type,count,value)
 */
static NC_attr *
new_NC_attr(
	const char *uname,
	nc_type type,
	size_t nelems)
{
	NC_string *strp = NULL;
	NC_attr *attrp = NULL;
	char *name = NULL;
	int stat = NC_NOERR;

	stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char**)&name);
	if(stat != NC_NOERR)
	    goto done;
	assert(name != NULL && *name != 0);

	strp = new_NC_string(strlen(name), name);
	if(strp == NULL)
		goto done;

	attrp = new_x_NC_attr(strp, type, nelems);
	if(attrp == NULL)
	{
		free_NC_string(strp);
		goto done;
	}
done:
	if(name) free(name);
	return (attrp);
}


static NC_attr *
dup_NC_attr(const NC_attr *rattrp)
{
	NC_attr *attrp = new_NC_attr(rattrp->name->cp,
		 rattrp->type, rattrp->nelems);
	if(attrp == NULL)
		return NULL;
        if(attrp->xvalue != NULL && rattrp->xvalue != NULL)
       	    (void) memcpy(attrp->xvalue, rattrp->xvalue, rattrp->xsz);
	return attrp;
}

/* attrarray */

/*
 * Free the stuff "in" (referred to by) an NC_attrarray.
 * Leaves the array itself allocated.
 */
void
free_NC_attrarrayV0(NC_attrarray *ncap)
{
	assert(ncap != NULL);

	if(ncap->nelems == 0)
		return;

	assert(ncap->value != NULL);

	{
		NC_attr **app = ncap->value;
		NC_attr *const *const end = &app[ncap->nelems];
		for( /*NADA*/; app < end; app++)
		{
			free_NC_attr(*app);
			*app = NULL;
		}
	}
	ncap->nelems = 0;
}


/*
 * Free NC_attrarray values.
 * formerly
NC_free_array()
 */
void
free_NC_attrarrayV(NC_attrarray *ncap)
{
	assert(ncap != NULL);

	if(ncap->nalloc == 0)
		return;

	assert(ncap->value != NULL);

	free_NC_attrarrayV0(ncap);

	free(ncap->value);
	ncap->value = NULL;
	ncap->nalloc = 0;
}


int
dup_NC_attrarrayV(NC_attrarray *ncap, const NC_attrarray *ref)
{
	int status = NC_NOERR;

	assert(ref != NULL);
	assert(ncap != NULL);

	if(ref->nelems != 0)
	{
		const size_t sz = ref->nelems * sizeof(NC_attr *);
		ncap->value = (NC_attr **) malloc(sz);
		if(ncap->value == NULL)
			return NC_ENOMEM;

		(void) memset(ncap->value, 0, sz);
		ncap->nalloc = ref->nelems;
	}

	ncap->nelems = 0;
	{
		NC_attr **app = ncap->value;
		const NC_attr **drpp = (const NC_attr **)ref->value;
		NC_attr *const *const end = &app[ref->nelems];
		for( /*NADA*/; app < end; drpp++, app++, ncap->nelems++)
		{
			*app = dup_NC_attr(*drpp);
			if(*app == NULL)
			{
				status = NC_ENOMEM;
				break;
			}
		}
	}

	if(status != NC_NOERR)
	{
		free_NC_attrarrayV(ncap);
		return status;
	}

	assert(ncap->nelems == ref->nelems);

	return NC_NOERR;
}


/*
 * Add a new handle on the end of an array of handles
 * Formerly
NC_incr_array(array, tail)
 */
static int
incr_NC_attrarray(NC_attrarray *ncap, NC_attr *newelemp)
{
	NC_attr **vp;

	assert(ncap != NULL);

	if(ncap->nalloc == 0)
	{
		assert(ncap->nelems == 0);
		vp = (NC_attr **) malloc(NC_ARRAY_GROWBY * sizeof(NC_attr *));
		if(vp == NULL)
			return NC_ENOMEM;

		ncap->value = vp;
		ncap->nalloc = NC_ARRAY_GROWBY;
	}
	else if(ncap->nelems +1 > ncap->nalloc)
	{
		vp = (NC_attr **) realloc(ncap->value,
			(ncap->nalloc + NC_ARRAY_GROWBY) * sizeof(NC_attr *));
		if(vp == NULL)
			return NC_ENOMEM;

		ncap->value = vp;
		ncap->nalloc += NC_ARRAY_GROWBY;
	}

	if(newelemp != NULL)
	{
		ncap->value[ncap->nelems] = newelemp;
		ncap->nelems++;
	}
	return NC_NOERR;
}


NC_attr *
elem_NC_attrarray(const NC_attrarray *ncap, size_t elem)
{
	assert(ncap != NULL);
	/* cast needed for braindead systems with signed size_t */
	if(ncap->nelems == 0 || (unsigned long) elem >= ncap->nelems)
		return NULL;

	assert(ncap->value != NULL);

	return ncap->value[elem];
}

/* End attarray per se */

/*
 * Given ncp and varid, return ptr to array of attributes
 *  else NULL on error
 */
static NC_attrarray *
NC_attrarray0(NC3_INFO* ncp, int varid)
{
	NC_attrarray *ap;

	if(varid == NC_GLOBAL) /* Global attribute, attach to cdf */
	{
		ap = &ncp->attrs;
	}
	else if(varid >= 0 && (size_t) varid < ncp->vars.nelems)
	{
		NC_var **vpp;
		vpp = (NC_var **)ncp->vars.value;
		vpp += varid;
		ap = &(*vpp)->attrs;
	} else {
		ap = NULL;
	}
	return(ap);
}


/*
 * Step thru NC_ATTRIBUTE array, seeking match on name.
 *  return match or NULL if Not Found or out of memory.
 */
NC_attr **
NC_findattr(const NC_attrarray *ncap, const char *uname)
{
	NC_attr **attrpp = NULL;
	size_t attrid;
	size_t slen;
	char *name = NULL;
	int stat = NC_NOERR;

	assert(ncap != NULL);

	if(ncap->nelems == 0)
	    goto done;

	/* normalized version of uname */
	stat = nc_utf8_normalize((const unsigned char *)uname,(unsigned char**)&name);
	if(stat != NC_NOERR)
	    goto done; /* TODO: need better way to indicate no memory */
	slen = strlen(name);

	attrpp = (NC_attr **) ncap->value;
	for(attrid = 0; attrid < ncap->nelems; attrid++, attrpp++)
	{
		if(strlen((*attrpp)->name->cp) == slen &&
			strncmp((*attrpp)->name->cp, name, slen) == 0)
		        goto done;
	}
	attrpp = NULL; /* not found */
done:
        if(name) free(name);
        return (attrpp); /* Normal return */
}


/*
 * Look up by ncid, varid and name, return NULL if not found
 */
static int
NC_lookupattr(int ncid,
	int varid,
	const char *name, /* attribute name */
	NC_attr **attrpp) /* modified on return */
{
	int status;
	NC* nc;
	NC3_INFO *ncp;
	NC_attrarray *ncap;
	NC_attr **tmp;

	status = NC_check_id(ncid, &nc);
	if(status != NC_NOERR)
		return status;
	ncp = NC3_DATA(nc);

	ncap = NC_attrarray0(ncp, varid);
	if(ncap == NULL)
		return NC_ENOTVAR;

	if(name == NULL)
		return NC_EBADNAME;

	tmp = NC_findattr(ncap, name);
	if(tmp == NULL)
		return NC_ENOTATT;

	if(attrpp != NULL)
		*attrpp = *tmp;

	return NC_NOERR;
}

/* Public */

int
NC3_inq_attname(int ncid, int varid, int attnum, char *name)
{
	int status;
	NC* nc;
	NC3_INFO *ncp;
	NC_attrarray *ncap;
	NC_attr *attrp;

	status = NC_check_id(ncid, &nc);
	if(status != NC_NOERR)
		return status;
	ncp = NC3_DATA(nc);

	ncap = NC_attrarray0(ncp, varid);
	if(ncap == NULL)
		return NC_ENOTVAR;

	attrp = elem_NC_attrarray(ncap, (size_t)attnum);
	if(attrp == NULL)
		return NC_ENOTATT;

	(void) strncpy(name, attrp->name->cp, attrp->name->nchars);
	name[attrp->name->nchars] = 0;

	return NC_NOERR;
}


int
NC3_inq_attid(int ncid, int varid, const char *name, int *attnump)
{
	int status;
	NC *nc;
	NC3_INFO* ncp;
	NC_attrarray *ncap;
	NC_attr **attrpp;

	status = NC_check_id(ncid, &nc);
	if(status != NC_NOERR)
		return status;
	ncp = NC3_DATA(nc);

	ncap = NC_attrarray0(ncp, varid);
	if(ncap == NULL)
		return NC_ENOTVAR;


	attrpp = NC_findattr(ncap, name);
	if(attrpp == NULL)
		return NC_ENOTATT;

	if(attnump != NULL)
		*attnump = (int)(attrpp - ncap->value);

	return NC_NOERR;
}

int
NC3_inq_att(int ncid,
	int varid,
	const char *name, /* input, attribute name */
	nc_type *datatypep,
	size_t *lenp)
{
	int status;
	NC_attr *attrp;

	status = NC_lookupattr(ncid, varid, name, &attrp);
	if(status != NC_NOERR)
		return status;

	if(datatypep != NULL)
		*datatypep = attrp->type;
	if(lenp != NULL)
		*lenp = attrp->nelems;

	return NC_NOERR;
}


int
NC3_rename_att( int ncid, int varid, const char *name, const char *unewname)
{
	int status = NC_NOERR;
	NC *nc = NULL;
	NC3_INFO* ncp = NULL;
	NC_attrarray *ncap = NULL;
	NC_attr **tmp = NULL;
	NC_attr *attrp = NULL;
	NC_string *newStr, *old;
	char *newname = NULL;  /* normalized version */

/* start sortof inline clone of NC_lookupattr() */

	status = NC_check_id(ncid, &nc);
	if(status != NC_NOERR)
		goto done;
	ncp = NC3_DATA(nc);

	if(NC_readonly(ncp))
		{status = NC_EPERM; goto done;}

	ncap = NC_attrarray0(ncp, varid);
	if(ncap == NULL)
		{status = NC_ENOTVAR; goto done;}

	status = NC_check_name(unewname);
	if(status != NC_NOERR)
		goto done;

	tmp = NC_findattr(ncap, name);
	if(tmp == NULL)
		{status = NC_ENOTATT; goto done;}
	attrp = *tmp;
/* end inline clone NC_lookupattr() */

	if(NC_findattr(ncap, unewname) != NULL)
	    {status = NC_ENAMEINUSE; goto done;} /* name in use */

	old = attrp->name;
	status = nc_utf8_normalize((const unsigned char *)unewname,(unsigned char**)&newname);
	if(status != NC_NOERR)
	    goto done;
	if(NC_indef(ncp))
	{
		newStr = new_NC_string(strlen(newname), newname);
		if( newStr == NULL)
			{status = NC_ENOMEM; goto done;}
		attrp->name = newStr;
		free_NC_string(old);
		goto done;
	}
	/* else not in define mode */

	/* If new name is longer than old, then complain,
           but otherwise, no change (test is same as set_NC_string)*/
	if(old->nchars < strlen(newname))
	    {status = NC_ENOTINDEFINE; goto done;}

	status = set_NC_string(old, newname);
	if( status != NC_NOERR)
		goto done;

	set_NC_hdirty(ncp);

	if(NC_doHsync(ncp))
	{
		status = NC_sync(ncp);
		if(status != NC_NOERR)
			goto done;
	}
done:
	if(newname) free(newname);
	return status;
}

int
NC3_del_att(int ncid, int varid, const char *uname)
{
	int status = NC_NOERR;
	NC *nc = NULL;
	NC3_INFO* ncp = NULL;
	NC_attrarray *ncap = NULL;
	NC_attr **attrpp = NULL;
	NC_attr *old = NULL;
	int attrid;
	size_t slen;
	char* name = NULL;

	status = NC_check_id(ncid, &nc);
	if(status != NC_NOERR)
		goto done;
	ncp = NC3_DATA(nc);

	if(!NC_indef(ncp))
		{status = NC_ENOTINDEFINE; goto done;}

	ncap = NC_attrarray0(ncp, varid);
	if(ncap == NULL)
		{status = NC_ENOTVAR; goto done;}

	status = nc_utf8_normalize((const unsigned char *)uname,(unsigned char**)&name);
	if(status != NC_NOERR)
	    goto done;

/* start sortof inline NC_findattr() */
	slen = strlen(name);

	attrpp = (NC_attr **) ncap->value;
	for(attrid = 0; (size_t) attrid < ncap->nelems; attrid++, attrpp++)
	    {
		if( slen == (*attrpp)->name->nchars &&
			strncmp(name, (*attrpp)->name->cp, slen) == 0)
		{
			old = *attrpp;
			break;
		}
	    }
	if( (size_t) attrid == ncap->nelems )
		{status = NC_ENOTATT; goto done;}
/* end inline NC_findattr() */

	/* shuffle down */
	for(attrid++; (size_t) attrid < ncap->nelems; attrid++)
	{
		*attrpp = *(attrpp + 1);
		attrpp++;
	}
	*attrpp = NULL;
	/* decrement count */
	ncap->nelems--;

	free_NC_attr(old);

done:
	if(name) free(name);
	return status;
}

#line 713

static int
#line 714
ncx_pad_putn_Iuchar(void **xpp, size_t nelems, const uchar *tp, nc_type type, void *fillp)
#line 714
{
#line 714
	switch(type) {
#line 714
	case NC_CHAR:
#line 714
		return NC_ECHAR;
#line 714
	case NC_BYTE:
#line 714
		return ncx_pad_putn_schar_uchar(xpp, nelems, tp, fillp);
#line 714
	case NC_SHORT:
#line 714
		return ncx_pad_putn_short_uchar(xpp, nelems, tp, fillp);
#line 714
	case NC_INT:
#line 714
		return ncx_putn_int_uchar(xpp, nelems, tp, fillp);
#line 714
	case NC_FLOAT:
#line 714
		return ncx_putn_float_uchar(xpp, nelems, tp, fillp);
#line 714
	case NC_DOUBLE:
#line 714
		return ncx_putn_double_uchar(xpp, nelems, tp, fillp);
#line 714
	case NC_UBYTE:
#line 714
		return ncx_pad_putn_uchar_uchar(xpp, nelems, tp, fillp);
#line 714
	case NC_USHORT:
#line 714
		return ncx_putn_ushort_uchar(xpp, nelems, tp, fillp);
#line 714
	case NC_UINT:
#line 714
		return ncx_putn_uint_uchar(xpp, nelems, tp, fillp);
#line 714
	case NC_INT64:
#line 714
		return ncx_putn_longlong_uchar(xpp, nelems, tp, fillp);
#line 714
	case NC_UINT64:
#line 714
		return ncx_putn_ulonglong_uchar(xpp, nelems, tp, fillp);
#line 714
	default:
#line 714
                assert("ncx_pad_putn_Iuchar invalid type" == 0);
#line 714
	}
#line 714
	return NC_EBADTYPE;
#line 714
}
#line 714

static int
#line 715
ncx_pad_getn_Iuchar(const void **xpp, size_t nelems, uchar *tp, nc_type type)
#line 715
{
#line 715
	switch(type) {
#line 715
	case NC_CHAR:
#line 715
		return NC_ECHAR;
#line 715
	case NC_BYTE:
#line 715
		return ncx_pad_getn_schar_uchar(xpp, nelems, tp);
#line 715
	case NC_SHORT:
#line 715
		return ncx_pad_getn_short_uchar(xpp, nelems, tp);
#line 715
	case NC_INT:
#line 715
		return ncx_getn_int_uchar(xpp, nelems, tp);
#line 715
	case NC_FLOAT:
#line 715
		return ncx_getn_float_uchar(xpp, nelems, tp);
#line 715
	case NC_DOUBLE:
#line 715
		return ncx_getn_double_uchar(xpp, nelems, tp);
#line 715
	case NC_UBYTE:
#line 715
		return ncx_pad_getn_uchar_uchar(xpp, nelems, tp);
#line 715
	case NC_USHORT:
#line 715
		return ncx_getn_ushort_uchar(xpp, nelems, tp);
#line 715
	case NC_UINT:
#line 715
		return ncx_getn_uint_uchar(xpp, nelems, tp);
#line 715
	case NC_INT64:
#line 715
		return ncx_getn_longlong_uchar(xpp, nelems, tp);
#line 715
	case NC_UINT64:
#line 715
		return ncx_getn_ulonglong_uchar(xpp, nelems, tp);
#line 715
	default:
#line 715
	        assert("ncx_pad_getn_Iuchar invalid type" == 0);
#line 715
	}
#line 715
	return NC_EBADTYPE;
#line 715
}
#line 715


static int
#line 717
ncx_pad_putn_Ischar(void **xpp, size_t nelems, const schar *tp, nc_type type, void *fillp)
#line 717
{
#line 717
	switch(type) {
#line 717
	case NC_CHAR:
#line 717
		return NC_ECHAR;
#line 717
	case NC_BYTE:
#line 717
		return ncx_pad_putn_schar_schar(xpp, nelems, tp, fillp);
#line 717
	case NC_SHORT:
#line 717
		return ncx_pad_putn_short_schar(xpp, nelems, tp, fillp);
#line 717
	case NC_INT:
#line 717
		return ncx_putn_int_schar(xpp, nelems, tp, fillp);
#line 717
	case NC_FLOAT:
#line 717
		return ncx_putn_float_schar(xpp, nelems, tp, fillp);
#line 717
	case NC_DOUBLE:
#line 717
		return ncx_putn_double_schar(xpp, nelems, tp, fillp);
#line 717
	case NC_UBYTE:
#line 717
		return ncx_pad_putn_uchar_schar(xpp, nelems, tp, fillp);
#line 717
	case NC_USHORT:
#line 717
		return ncx_putn_ushort_schar(xpp, nelems, tp, fillp);
#line 717
	case NC_UINT:
#line 717
		return ncx_putn_uint_schar(xpp, nelems, tp, fillp);
#line 717
	case NC_INT64:
#line 717
		return ncx_putn_longlong_schar(xpp, nelems, tp, fillp);
#line 717
	case NC_UINT64:
#line 717
		return ncx_putn_ulonglong_schar(xpp, nelems, tp, fillp);
#line 717
	default:
#line 717
                assert("ncx_pad_putn_Ischar invalid type" == 0);
#line 717
	}
#line 717
	return NC_EBADTYPE;
#line 717
}
#line 717

static int
#line 718
ncx_pad_getn_Ischar(const void **xpp, size_t nelems, schar *tp, nc_type type)
#line 718
{
#line 718
	switch(type) {
#line 718
	case NC_CHAR:
#line 718
		return NC_ECHAR;
#line 718
	case NC_BYTE:
#line 718
		return ncx_pad_getn_schar_schar(xpp, nelems, tp);
#line 718
	case NC_SHORT:
#line 718
		return ncx_pad_getn_short_schar(xpp, nelems, tp);
#line 718
	case NC_INT:
#line 718
		return ncx_getn_int_schar(xpp, nelems, tp);
#line 718
	case NC_FLOAT:
#line 718
		return ncx_getn_float_schar(xpp, nelems, tp);
#line 718
	case NC_DOUBLE:
#line 718
		return ncx_getn_double_schar(xpp, nelems, tp);
#line 718
	case NC_UBYTE:
#line 718
		return ncx_pad_getn_uchar_schar(xpp, nelems, tp);
#line 718
	case NC_USHORT:
#line 718
		return ncx_getn_ushort_schar(xpp, nelems, tp);
#line 718
	case NC_UINT:
#line 718
		return ncx_getn_uint_schar(xpp, nelems, tp);
#line 718
	case NC_INT64:
#line 718
		return ncx_getn_longlong_schar(xpp, nelems, tp);
#line 718
	case NC_UINT64:
#line 718
		return ncx_getn_ulonglong_schar(xpp, nelems, tp);
#line 718
	default:
#line 718
	        assert("ncx_pad_getn_Ischar invalid type" == 0);
#line 718
	}
#line 718
	return NC_EBADTYPE;
#line 718
}
#line 718


static int
#line 720
ncx_pad_putn_Ishort(void **xpp, size_t nelems, const short *tp, nc_type type, void *fillp)
#line 720
{
#line 720
	switch(type) {
#line 720
	case NC_CHAR:
#line 720
		return NC_ECHAR;
#line 720
	case NC_BYTE:
#line 720
		return ncx_pad_putn_schar_short(xpp, nelems, tp, fillp);
#line 720
	case NC_SHORT:
#line 720
		return ncx_pad_putn_short_short(xpp, nelems, tp, fillp);
#line 720
	case NC_INT:
#line 720
		return ncx_putn_int_short(xpp, nelems, tp, fillp);
#line 720
	case NC_FLOAT:
#line 720
		return ncx_putn_float_short(xpp, nelems, tp, fillp);
#line 720
	case NC_DOUBLE:
#line 720
		return ncx_putn_double_short(xpp, nelems, tp, fillp);
#line 720
	case NC_UBYTE:
#line 720
		return ncx_pad_putn_uchar_short(xpp, nelems, tp, fillp);
#line 720
	case NC_USHORT:
#line 720
		return ncx_putn_ushort_short(xpp, nelems, tp, fillp);
#line 720
	case NC_UINT:
#line 720
		return ncx_putn_uint_short(xpp, nelems, tp, fillp);
#line 720
	case NC_INT64:
#line 720
		return ncx_putn_longlong_short(xpp, nelems, tp, fillp);
#line 720
	case NC_UINT64:
#line 720
		return ncx_putn_ulonglong_short(xpp, nelems, tp, fillp);
#line 720
	default:
#line 720
                assert("ncx_pad_putn_Ishort invalid type" == 0);
#line 720
	}
#line 720
	return NC_EBADTYPE;
#line 720
}
#line 720

static int
#line 721
ncx_pad_getn_Ishort(const void **xpp, size_t nelems, short *tp, nc_type type)
#line 721
{
#line 721
	switch(type) {
#line 721
	case NC_CHAR:
#line 721
		return NC_ECHAR;
#line 721
	case NC_BYTE:
#line 721
		return ncx_pad_getn_schar_short(xpp, nelems, tp);
#line 721
	case NC_SHORT:
#line 721
		return ncx_pad_getn_short_short(xpp, nelems, tp);
#line 721
	case NC_INT:
#line 721
		return ncx_getn_int_short(xpp, nelems, tp);
#line 721
	case NC_FLOAT:
#line 721
		return ncx_getn_float_short(xpp, nelems, tp);
#line 721
	case NC_DOUBLE:
#line 721
		return ncx_getn_double_short(xpp, nelems, tp);
#line 721
	case NC_UBYTE:
#line 721
		return ncx_pad_getn_uchar_short(xpp, nelems, tp);
#line 721
	case NC_USHORT:
#line 721
		return ncx_getn_ushort_short(xpp, nelems, tp);
#line 721
	case NC_UINT:
#line 721
		return ncx_getn_uint_short(xpp, nelems, tp);
#line 721
	case NC_INT64:
#line 721
		return ncx_getn_longlong_short(xpp, nelems, tp);
#line 721
	case NC_UINT64:
#line 721
		return ncx_getn_ulonglong_short(xpp, nelems, tp);
#line 721
	default:
#line 721
	        assert("ncx_pad_getn_Ishort invalid type" == 0);
#line 721
	}
#line 721
	return NC_EBADTYPE;
#line 721
}
#line 721


static int
#line 723
ncx_pad_putn_Iint(void **xpp, size_t nelems, const int *tp, nc_type type, void *fillp)
#line 723
{
#line 723
	switch(type) {
#line 723
	case NC_CHAR:
#line 723
		return NC_ECHAR;
#line 723
	case NC_BYTE:
#line 723
		return ncx_pad_putn_schar_int(xpp, nelems, tp, fillp);
#line 723
	case NC_SHORT:
#line 723
		return ncx_pad_putn_short_int(xpp, nelems, tp, fillp);
#line 723
	case NC_INT:
#line 723
		return ncx_putn_int_int(xpp, nelems, tp, fillp);
#line 723
	case NC_FLOAT:
#line 723
		return ncx_putn_float_int(xpp, nelems, tp, fillp);
#line 723
	case NC_DOUBLE:
#line 723
		return ncx_putn_double_int(xpp, nelems, tp, fillp);
#line 723
	case NC_UBYTE:
#line 723
		return ncx_pad_putn_uchar_int(xpp, nelems, tp, fillp);
#line 723
	case NC_USHORT:
#line 723
		return ncx_putn_ushort_int(xpp, nelems, tp, fillp);
#line 723
	case NC_UINT:
#line 723
		return ncx_putn_uint_int(xpp, nelems, tp, fillp);
#line 723
	case NC_INT64:
#line 723
		return ncx_putn_longlong_int(xpp, nelems, tp, fillp);
#line 723
	case NC_UINT64:
#line 723
		return ncx_putn_ulonglong_int(xpp, nelems, tp, fillp);
#line 723
	default:
#line 723
                assert("ncx_pad_putn_Iint invalid type" == 0);
#line 723
	}
#line 723
	return NC_EBADTYPE;
#line 723
}
#line 723

static int
#line 724
ncx_pad_getn_Iint(const void **xpp, size_t nelems, int *tp, nc_type type)
#line 724
{
#line 724
	switch(type) {
#line 724
	case NC_CHAR:
#line 724
		return NC_ECHAR;
#line 724
	case NC_BYTE:
#line 724
		return ncx_pad_getn_schar_int(xpp, nelems, tp);
#line 724
	case NC_SHORT:
#line 724
		return ncx_pad_getn_short_int(xpp, nelems, tp);
#line 724
	case NC_INT:
#line 724
		return ncx_getn_int_int(xpp, nelems, tp);
#line 724
	case NC_FLOAT:
#line 724
		return ncx_getn_float_int(xpp, nelems, tp);
#line 724
	case NC_DOUBLE:
#line 724
		return ncx_getn_double_int(xpp, nelems, tp);
#line 724
	case NC_UBYTE:
#line 724
		return ncx_pad_getn_uchar_int(xpp, nelems, tp);
#line 724
	case NC_USHORT:
#line 724
		return ncx_getn_ushort_int(xpp, nelems, tp);
#line 724
	case NC_UINT:
#line 724
		return ncx_getn_uint_int(xpp, nelems, tp);
#line 724
	case NC_INT64:
#line 724
		return ncx_getn_longlong_int(xpp, nelems, tp);
#line 724
	case NC_UINT64:
#line 724
		return ncx_getn_ulonglong_int(xpp, nelems, tp);
#line 724
	default:
#line 724
	        assert("ncx_pad_getn_Iint invalid type" == 0);
#line 724
	}
#line 724
	return NC_EBADTYPE;
#line 724
}
#line 724


static int
#line 726
ncx_pad_putn_Ifloat(void **xpp, size_t nelems, const float *tp, nc_type type, void *fillp)
#line 726
{
#line 726
	switch(type) {
#line 726
	case NC_CHAR:
#line 726
		return NC_ECHAR;
#line 726
	case NC_BYTE:
#line 726
		return ncx_pad_putn_schar_float(xpp, nelems, tp, fillp);
#line 726
	case NC_SHORT:
#line 726
		return ncx_pad_putn_short_float(xpp, nelems, tp, fillp);
#line 726
	case NC_INT:
#line 726
		return ncx_putn_int_float(xpp, nelems, tp, fillp);
#line 726
	case NC_FLOAT:
#line 726
		return ncx_putn_float_float(xpp, nelems, tp, fillp);
#line 726
	case NC_DOUBLE:
#line 726
		return ncx_putn_double_float(xpp, nelems, tp, fillp);
#line 726
	case NC_UBYTE:
#line 726
		return ncx_pad_putn_uchar_float(xpp, nelems, tp, fillp);
#line 726
	case NC_USHORT:
#line 726
		return ncx_putn_ushort_float(xpp, nelems, tp, fillp);
#line 726
	case NC_UINT:
#line 726
		return ncx_putn_uint_float(xpp, nelems, tp, fillp);
#line 726
	case NC_INT64:
#line 726
		return ncx_putn_longlong_float(xpp, nelems, tp, fillp);
#line 726
	case NC_UINT64:
#line 726
		return ncx_putn_ulonglong_float(xpp, nelems, tp, fillp);
#line 726
	default:
#line 726
                assert("ncx_pad_putn_Ifloat invalid type" == 0);
#line 726
	}
#line 726
	return NC_EBADTYPE;
#line 726
}
#line 726

static int
#line 727
ncx_pad_getn_Ifloat(const void **xpp, size_t nelems, float *tp, nc_type type)
#line 727
{
#line 727
	switch(type) {
#line 727
	case NC_CHAR:
#line 727
		return NC_ECHAR;
#line 727
	case NC_BYTE:
#line 727
		return ncx_pad_getn_schar_float(xpp, nelems, tp);
#line 727
	case NC_SHORT:
#line 727
		return ncx_pad_getn_short_float(xpp, nelems, tp);
#line 727
	case NC_INT:
#line 727
		return ncx_getn_int_float(xpp, nelems, tp);
#line 727
	case NC_FLOAT:
#line 727
		return ncx_getn_float_float(xpp, nelems, tp);
#line 727
	case NC_DOUBLE:
#line 727
		return ncx_getn_double_float(xpp, nelems, tp);
#line 727
	case NC_UBYTE:
#line 727
		return ncx_pad_getn_uchar_float(xpp, nelems, tp);
#line 727
	case NC_USHORT:
#line 727
		return ncx_getn_ushort_float(xpp, nelems, tp);
#line 727
	case NC_UINT:
#line 727
		return ncx_getn_uint_float(xpp, nelems, tp);
#line 727
	case NC_INT64:
#line 727
		return ncx_getn_longlong_float(xpp, nelems, tp);
#line 727
	case NC_UINT64:
#line 727
		return ncx_getn_ulonglong_float(xpp, nelems, tp);
#line 727
	default:
#line 727
	        assert("ncx_pad_getn_Ifloat invalid type" == 0);
#line 727
	}
#line 727
	return NC_EBADTYPE;
#line 727
}
#line 727


static int
#line 729
ncx_pad_putn_Idouble(void **xpp, size_t nelems, const double *tp, nc_type type, void *fillp)
#line 729
{
#line 729
	switch(type) {
#line 729
	case NC_CHAR:
#line 729
		return NC_ECHAR;
#line 729
	case NC_BYTE:
#line 729
		return ncx_pad_putn_schar_double(xpp, nelems, tp, fillp);
#line 729
	case NC_SHORT:
#line 729
		return ncx_pad_putn_short_double(xpp, nelems, tp, fillp);
#line 729
	case NC_INT:
#line 729
		return ncx_putn_int_double(xpp, nelems, tp, fillp);
#line 729
	case NC_FLOAT:
#line 729
		return ncx_putn_float_double(xpp, nelems, tp, fillp);
#line 729
	case NC_DOUBLE:
#line 729
		return ncx_putn_double_double(xpp, nelems, tp, fillp);
#line 729
	case NC_UBYTE:
#line 729
		return ncx_pad_putn_uchar_double(xpp, nelems, tp, fillp);
#line 729
	case NC_USHORT:
#line 729
		return ncx_putn_ushort_double(xpp, nelems, tp, fillp);
#line 729
	case NC_UINT:
#line 729
		return ncx_putn_uint_double(xpp, nelems, tp, fillp);
#line 729
	case NC_INT64:
#line 729
		return ncx_putn_longlong_double(xpp, nelems, tp, fillp);
#line 729
	case NC_UINT64:
#line 729
		return ncx_putn_ulonglong_double(xpp, nelems, tp, fillp);
#line 729
	default:
#line 729
                assert("ncx_pad_putn_Idouble invalid type" == 0);
#line 729
	}
#line 729
	return NC_EBADTYPE;
#line 729
}
#line 729

static int
#line 730
ncx_pad_getn_Idouble(const void **xpp, size_t nelems, double *tp, nc_type type)
#line 730
{
#line 730
	switch(type) {
#line 730
	case NC_CHAR:
#line 730
		return NC_ECHAR;
#line 730
	case NC_BYTE:
#line 730
		return ncx_pad_getn_schar_double(xpp, nelems, tp);
#line 730
	case NC_SHORT:
#line 730
		return ncx_pad_getn_short_double(xpp, nelems, tp);
#line 730
	case NC_INT:
#line 730
		return ncx_getn_int_double(xpp, nelems, tp);
#line 730
	case NC_FLOAT:
#line 730
		return ncx_getn_float_double(xpp, nelems, tp);
#line 730
	case NC_DOUBLE:
#line 730
		return ncx_getn_double_double(xpp, nelems, tp);
#line 730
	case NC_UBYTE:
#line 730
		return ncx_pad_getn_uchar_double(xpp, nelems, tp);
#line 730
	case NC_USHORT:
#line 730
		return ncx_getn_ushort_double(xpp, nelems, tp);
#line 730
	case NC_UINT:
#line 730
		return ncx_getn_uint_double(xpp, nelems, tp);
#line 730
	case NC_INT64:
#line 730
		return ncx_getn_longlong_double(xpp, nelems, tp);
#line 730
	case NC_UINT64:
#line 730
		return ncx_getn_ulonglong_double(xpp, nelems, tp);
#line 730
	default:
#line 730
	        assert("ncx_pad_getn_Idouble invalid type" == 0);
#line 730
	}
#line 730
	return NC_EBADTYPE;
#line 730
}
#line 730


#ifdef IGNORE
static int
#line 733
ncx_pad_putn_Ilong(void **xpp, size_t nelems, const long *tp, nc_type type, void *fillp)
#line 733
{
#line 733
	switch(type) {
#line 733
	case NC_CHAR:
#line 733
		return NC_ECHAR;
#line 733
	case NC_BYTE:
#line 733
		return ncx_pad_putn_schar_long(xpp, nelems, tp, fillp);
#line 733
	case NC_SHORT:
#line 733
		return ncx_pad_putn_short_long(xpp, nelems, tp, fillp);
#line 733
	case NC_INT:
#line 733
		return ncx_putn_int_long(xpp, nelems, tp, fillp);
#line 733
	case NC_FLOAT:
#line 733
		return ncx_putn_float_long(xpp, nelems, tp, fillp);
#line 733
	case NC_DOUBLE:
#line 733
		return ncx_putn_double_long(xpp, nelems, tp, fillp);
#line 733
	case NC_UBYTE:
#line 733
		return ncx_pad_putn_uchar_long(xpp, nelems, tp, fillp);
#line 733
	case NC_USHORT:
#line 733
		return ncx_putn_ushort_long(xpp, nelems, tp, fillp);
#line 733
	case NC_UINT:
#line 733
		return ncx_putn_uint_long(xpp, nelems, tp, fillp);
#line 733
	case NC_INT64:
#line 733
		return ncx_putn_longlong_long(xpp, nelems, tp, fillp);
#line 733
	case NC_UINT64:
#line 733
		return ncx_putn_ulonglong_long(xpp, nelems, tp, fillp);
#line 733
	default:
#line 733
                assert("ncx_pad_putn_Ilong invalid type" == 0);
#line 733
	}
#line 733
	return NC_EBADTYPE;
#line 733
}
#line 733

static int
#line 734
ncx_pad_getn_Ilong(const void **xpp, size_t nelems, long *tp, nc_type type)
#line 734
{
#line 734
	switch(type) {
#line 734
	case NC_CHAR:
#line 734
		return NC_ECHAR;
#line 734
	case NC_BYTE:
#line 734
		return ncx_pad_getn_schar_long(xpp, nelems, tp);
#line 734
	case NC_SHORT:
#line 734
		return ncx_pad_getn_short_long(xpp, nelems, tp);
#line 734
	case NC_INT:
#line 734
		return ncx_getn_int_long(xpp, nelems, tp);
#line 734
	case NC_FLOAT:
#line 734
		return ncx_getn_float_long(xpp, nelems, tp);
#line 734
	case NC_DOUBLE:
#line 734
		return ncx_getn_double_long(xpp, nelems, tp);
#line 734
	case NC_UBYTE:
#line 734
		return ncx_pad_getn_uchar_long(xpp, nelems, tp);
#line 734
	case NC_USHORT:
#line 734
		return ncx_getn_ushort_long(xpp, nelems, tp);
#line 734
	case NC_UINT:
#line 734
		return ncx_getn_uint_long(xpp, nelems, tp);
#line 734
	case NC_INT64:
#line 734
		return ncx_getn_longlong_long(xpp, nelems, tp);
#line 734
	case NC_UINT64:
#line 734
		return ncx_getn_ulonglong_long(xpp, nelems, tp);
#line 734
	default:
#line 734
	        assert("ncx_pad_getn_Ilong invalid type" == 0);
#line 734
	}
#line 734
	return NC_EBADTYPE;
#line 734
}
#line 734

#endif

static int
#line 737
ncx_pad_putn_Ilonglong(void **xpp, size_t nelems, const longlong *tp, nc_type type, void *fillp)
#line 737
{
#line 737
	switch(type) {
#line 737
	case NC_CHAR:
#line 737
		return NC_ECHAR;
#line 737
	case NC_BYTE:
#line 737
		return ncx_pad_putn_schar_longlong(xpp, nelems, tp, fillp);
#line 737
	case NC_SHORT:
#line 737
		return ncx_pad_putn_short_longlong(xpp, nelems, tp, fillp);
#line 737
	case NC_INT:
#line 737
		return ncx_putn_int_longlong(xpp, nelems, tp, fillp);
#line 737
	case NC_FLOAT:
#line 737
		return ncx_putn_float_longlong(xpp, nelems, tp, fillp);
#line 737
	case NC_DOUBLE:
#line 737
		return ncx_putn_double_longlong(xpp, nelems, tp, fillp);
#line 737
	case NC_UBYTE:
#line 737
		return ncx_pad_putn_uchar_longlong(xpp, nelems, tp, fillp);
#line 737
	case NC_USHORT:
#line 737
		return ncx_putn_ushort_longlong(xpp, nelems, tp, fillp);
#line 737
	case NC_UINT:
#line 737
		return ncx_putn_uint_longlong(xpp, nelems, tp, fillp);
#line 737
	case NC_INT64:
#line 737
		return ncx_putn_longlong_longlong(xpp, nelems, tp, fillp);
#line 737
	case NC_UINT64:
#line 737
		return ncx_putn_ulonglong_longlong(xpp, nelems, tp, fillp);
#line 737
	default:
#line 737
                assert("ncx_pad_putn_Ilonglong invalid type" == 0);
#line 737
	}
#line 737
	return NC_EBADTYPE;
#line 737
}
#line 737

static int
#line 738
ncx_pad_getn_Ilonglong(const void **xpp, size_t nelems, longlong *tp, nc_type type)
#line 738
{
#line 738
	switch(type) {
#line 738
	case NC_CHAR:
#line 738
		return NC_ECHAR;
#line 738
	case NC_BYTE:
#line 738
		return ncx_pad_getn_schar_longlong(xpp, nelems, tp);
#line 738
	case NC_SHORT:
#line 738
		return ncx_pad_getn_short_longlong(xpp, nelems, tp);
#line 738
	case NC_INT:
#line 738
		return ncx_getn_int_longlong(xpp, nelems, tp);
#line 738
	case NC_FLOAT:
#line 738
		return ncx_getn_float_longlong(xpp, nelems, tp);
#line 738
	case NC_DOUBLE:
#line 738
		return ncx_getn_double_longlong(xpp, nelems, tp);
#line 738
	case NC_UBYTE:
#line 738
		return ncx_pad_getn_uchar_longlong(xpp, nelems, tp);
#line 738
	case NC_USHORT:
#line 738
		return ncx_getn_ushort_longlong(xpp, nelems, tp);
#line 738
	case NC_UINT:
#line 738
		return ncx_getn_uint_longlong(xpp, nelems, tp);
#line 738
	case NC_INT64:
#line 738
		return ncx_getn_longlong_longlong(xpp, nelems, tp);
#line 738
	case NC_UINT64:
#line 738
		return ncx_getn_ulonglong_longlong(xpp, nelems, tp);
#line 738
	default:
#line 738
	        assert("ncx_pad_getn_Ilonglong invalid type" == 0);
#line 738
	}
#line 738
	return NC_EBADTYPE;
#line 738
}
#line 738


static int
#line 740
ncx_pad_putn_Iushort(void **xpp, size_t nelems, const ushort *tp, nc_type type, void *fillp)
#line 740
{
#line 740
	switch(type) {
#line 740
	case NC_CHAR:
#line 740
		return NC_ECHAR;
#line 740
	case NC_BYTE:
#line 740
		return ncx_pad_putn_schar_ushort(xpp, nelems, tp, fillp);
#line 740
	case NC_SHORT:
#line 740
		return ncx_pad_putn_short_ushort(xpp, nelems, tp, fillp);
#line 740
	case NC_INT:
#line 740
		return ncx_putn_int_ushort(xpp, nelems, tp, fillp);
#line 740
	case NC_FLOAT:
#line 740
		return ncx_putn_float_ushort(xpp, nelems, tp, fillp);
#line 740
	case NC_DOUBLE:
#line 740
		return ncx_putn_double_ushort(xpp, nelems, tp, fillp);
#line 740
	case NC_UBYTE:
#line 740
		return ncx_pad_putn_uchar_ushort(xpp, nelems, tp, fillp);
#line 740
	case NC_USHORT:
#line 740
		return ncx_putn_ushort_ushort(xpp, nelems, tp, fillp);
#line 740
	case NC_UINT:
#line 740
		return ncx_putn_uint_ushort(xpp, nelems, tp, fillp);
#line 740
	case NC_INT64:
#line 740
		return ncx_putn_longlong_ushort(xpp, nelems, tp, fillp);
#line 740
	case NC_UINT64:
#line 740
		return ncx_putn_ulonglong_ushort(xpp, nelems, tp, fillp);
#line 740
	default:
#line 740
                assert("ncx_pad_putn_Iushort invalid type" == 0);
#line 740
	}
#line 740
	return NC_EBADTYPE;
#line 740
}
#line 740

static int
#line 741
ncx_pad_getn_Iushort(const void **xpp, size_t nelems, ushort *tp, nc_type type)
#line 741
{
#line 741
	switch(type) {
#line 741
	case NC_CHAR:
#line 741
		return NC_ECHAR;
#line 741
	case NC_BYTE:
#line 741
		return ncx_pad_getn_schar_ushort(xpp, nelems, tp);
#line 741
	case NC_SHORT:
#line 741
		return ncx_pad_getn_short_ushort(xpp, nelems, tp);
#line 741
	case NC_INT:
#line 741
		return ncx_getn_int_ushort(xpp, nelems, tp);
#line 741
	case NC_FLOAT:
#line 741
		return ncx_getn_float_ushort(xpp, nelems, tp);
#line 741
	case NC_DOUBLE:
#line 741
		return ncx_getn_double_ushort(xpp, nelems, tp);
#line 741
	case NC_UBYTE:
#line 741
		return ncx_pad_getn_uchar_ushort(xpp, nelems, tp);
#line 741
	case NC_USHORT:
#line 741
		return ncx_getn_ushort_ushort(xpp, nelems, tp);
#line 741
	case NC_UINT:
#line 741
		return ncx_getn_uint_ushort(xpp, nelems, tp);
#line 741
	case NC_INT64:
#line 741
		return ncx_getn_longlong_ushort(xpp, nelems, tp);
#line 741
	case NC_UINT64:
#line 741
		return ncx_getn_ulonglong_ushort(xpp, nelems, tp);
#line 741
	default:
#line 741
	        assert("ncx_pad_getn_Iushort invalid type" == 0);
#line 741
	}
#line 741
	return NC_EBADTYPE;
#line 741
}
#line 741


static int
#line 743
ncx_pad_putn_Iuint(void **xpp, size_t nelems, const uint *tp, nc_type type, void *fillp)
#line 743
{
#line 743
	switch(type) {
#line 743
	case NC_CHAR:
#line 743
		return NC_ECHAR;
#line 743
	case NC_BYTE:
#line 743
		return ncx_pad_putn_schar_uint(xpp, nelems, tp, fillp);
#line 743
	case NC_SHORT:
#line 743
		return ncx_pad_putn_short_uint(xpp, nelems, tp, fillp);
#line 743
	case NC_INT:
#line 743
		return ncx_putn_int_uint(xpp, nelems, tp, fillp);
#line 743
	case NC_FLOAT:
#line 743
		return ncx_putn_float_uint(xpp, nelems, tp, fillp);
#line 743
	case NC_DOUBLE:
#line 743
		return ncx_putn_double_uint(xpp, nelems, tp, fillp);
#line 743
	case NC_UBYTE:
#line 743
		return ncx_pad_putn_uchar_uint(xpp, nelems, tp, fillp);
#line 743
	case NC_USHORT:
#line 743
		return ncx_putn_ushort_uint(xpp, nelems, tp, fillp);
#line 743
	case NC_UINT:
#line 743
		return ncx_putn_uint_uint(xpp, nelems, tp, fillp);
#line 743
	case NC_INT64:
#line 743
		return ncx_putn_longlong_uint(xpp, nelems, tp, fillp);
#line 743
	case NC_UINT64:
#line 743
		return ncx_putn_ulonglong_uint(xpp, nelems, tp, fillp);
#line 743
	default:
#line 743
                assert("ncx_pad_putn_Iuint invalid type" == 0);
#line 743
	}
#line 743
	return NC_EBADTYPE;
#line 743
}
#line 743

static int
#line 744
ncx_pad_getn_Iuint(const void **xpp, size_t nelems, uint *tp, nc_type type)
#line 744
{
#line 744
	switch(type) {
#line 744
	case NC_CHAR:
#line 744
		return NC_ECHAR;
#line 744
	case NC_BYTE:
#line 744
		return ncx_pad_getn_schar_uint(xpp, nelems, tp);
#line 744
	case NC_SHORT:
#line 744
		return ncx_pad_getn_short_uint(xpp, nelems, tp);
#line 744
	case NC_INT:
#line 744
		return ncx_getn_int_uint(xpp, nelems, tp);
#line 744
	case NC_FLOAT:
#line 744
		return ncx_getn_float_uint(xpp, nelems, tp);
#line 744
	case NC_DOUBLE:
#line 744
		return ncx_getn_double_uint(xpp, nelems, tp);
#line 744
	case NC_UBYTE:
#line 744
		return ncx_pad_getn_uchar_uint(xpp, nelems, tp);
#line 744
	case NC_USHORT:
#line 744
		return ncx_getn_ushort_uint(xpp, nelems, tp);
#line 744
	case NC_UINT:
#line 744
		return ncx_getn_uint_uint(xpp, nelems, tp);
#line 744
	case NC_INT64:
#line 744
		return ncx_getn_longlong_uint(xpp, nelems, tp);
#line 744
	case NC_UINT64:
#line 744
		return ncx_getn_ulonglong_uint(xpp, nelems, tp);
#line 744
	default:
#line 744
	        assert("ncx_pad_getn_Iuint invalid type" == 0);
#line 744
	}
#line 744
	return NC_EBADTYPE;
#line 744
}
#line 744


static int
#line 746
ncx_pad_putn_Iulonglong(void **xpp, size_t nelems, const ulonglong *tp, nc_type type, void *fillp)
#line 746
{
#line 746
	switch(type) {
#line 746
	case NC_CHAR:
#line 746
		return NC_ECHAR;
#line 746
	case NC_BYTE:
#line 746
		return ncx_pad_putn_schar_ulonglong(xpp, nelems, tp, fillp);
#line 746
	case NC_SHORT:
#line 746
		return ncx_pad_putn_short_ulonglong(xpp, nelems, tp, fillp);
#line 746
	case NC_INT:
#line 746
		return ncx_putn_int_ulonglong(xpp, nelems, tp, fillp);
#line 746
	case NC_FLOAT:
#line 746
		return ncx_putn_float_ulonglong(xpp, nelems, tp, fillp);
#line 746
	case NC_DOUBLE:
#line 746
		return ncx_putn_double_ulonglong(xpp, nelems, tp, fillp);
#line 746
	case NC_UBYTE:
#line 746
		return ncx_pad_putn_uchar_ulonglong(xpp, nelems, tp, fillp);
#line 746
	case NC_USHORT:
#line 746
		return ncx_putn_ushort_ulonglong(xpp, nelems, tp, fillp);
#line 746
	case NC_UINT:
#line 746
		return ncx_putn_uint_ulonglong(xpp, nelems, tp, fillp);
#line 746
	case NC_INT64:
#line 746
		return ncx_putn_longlong_ulonglong(xpp, nelems, tp, fillp);
#line 746
	case NC_UINT64:
#line 746
		return ncx_putn_ulonglong_ulonglong(xpp, nelems, tp, fillp);
#line 746
	default:
#line 746
                assert("ncx_pad_putn_Iulonglong invalid type" == 0);
#line 746
	}
#line 746
	return NC_EBADTYPE;
#line 746
}
#line 746

static int
#line 747
ncx_pad_getn_Iulonglong(const void **xpp, size_t nelems, ulonglong *tp, nc_type type)
#line 747
{
#line 747
	switch(type) {
#line 747
	case NC_CHAR:
#line 747
		return NC_ECHAR;
#line 747
	case NC_BYTE:
#line 747
		return ncx_pad_getn_schar_ulonglong(xpp, nelems, tp);
#line 747
	case NC_SHORT:
#line 747
		return ncx_pad_getn_short_ulonglong(xpp, nelems, tp);
#line 747
	case NC_INT:
#line 747
		return ncx_getn_int_ulonglong(xpp, nelems, tp);
#line 747
	case NC_FLOAT:
#line 747
		return ncx_getn_float_ulonglong(xpp, nelems, tp);
#line 747
	case NC_DOUBLE:
#line 747
		return ncx_getn_double_ulonglong(xpp, nelems, tp);
#line 747
	case NC_UBYTE:
#line 747
		return ncx_pad_getn_uchar_ulonglong(xpp, nelems, tp);
#line 747
	case NC_USHORT:
#line 747
		return ncx_getn_ushort_ulonglong(xpp, nelems, tp);
#line 747
	case NC_UINT:
#line 747
		return ncx_getn_uint_ulonglong(xpp, nelems, tp);
#line 747
	case NC_INT64:
#line 747
		return ncx_getn_longlong_ulonglong(xpp, nelems, tp);
#line 747
	case NC_UINT64:
#line 747
		return ncx_getn_ulonglong_ulonglong(xpp, nelems, tp);
#line 747
	default:
#line 747
	        assert("ncx_pad_getn_Iulonglong invalid type" == 0);
#line 747
	}
#line 747
	return NC_EBADTYPE;
#line 747
}
#line 747



/* Common dispatcher for put cases */
static int
dispatchput(void **xpp, size_t nelems, const void* tp,
	    nc_type atype, nc_type memtype, void *fillp)
{
    switch (memtype) {
    case NC_CHAR:
        return ncx_pad_putn_text(xpp,nelems, (char *)tp);
    case NC_BYTE:
        return ncx_pad_putn_Ischar(xpp, nelems, (schar*)tp, atype, fillp);
    case NC_SHORT:
        return ncx_pad_putn_Ishort(xpp, nelems, (short*)tp, atype, fillp);
    case NC_INT:
          return ncx_pad_putn_Iint(xpp, nelems, (int*)tp, atype, fillp);
    case NC_FLOAT:
        return ncx_pad_putn_Ifloat(xpp, nelems, (float*)tp, atype, fillp);
    case NC_DOUBLE:
        return ncx_pad_putn_Idouble(xpp, nelems, (double*)tp, atype, fillp);
    case NC_UBYTE: /*Synthetic*/
        return ncx_pad_putn_Iuchar(xpp,nelems, (uchar *)tp, atype, fillp);
    case NC_INT64:
          return ncx_pad_putn_Ilonglong(xpp, nelems, (longlong*)tp, atype, fillp);
    case NC_USHORT:
          return ncx_pad_putn_Iushort(xpp, nelems, (ushort*)tp, atype, fillp);
    case NC_UINT:
          return ncx_pad_putn_Iuint(xpp, nelems, (uint*)tp, atype, fillp);
    case NC_UINT64:
          return ncx_pad_putn_Iulonglong(xpp, nelems, (ulonglong*)tp, atype, fillp);
    case NC_NAT:
        return NC_EBADTYPE;
    default:
        break;
    }
    return NC_EBADTYPE;
}

int
NC3_put_att(
	int ncid,
	int varid,
	const char *name,
	nc_type type,
	size_t nelems,
	const void *value,
	nc_type memtype)
{
    int status;
    NC *nc;
    NC3_INFO* ncp;
    NC_attrarray *ncap;
    NC_attr **attrpp;
    NC_attr *old = NULL;
    NC_attr *attrp;
    unsigned char fill[8]; /* fill value in internal representation */

    status = NC_check_id(ncid, &nc);
    if(status != NC_NOERR)
	return status;
    ncp = NC3_DATA(nc);

    if(NC_readonly(ncp))
	return NC_EPERM;

    ncap = NC_attrarray0(ncp, varid);
    if(ncap == NULL)
	return NC_ENOTVAR;

    if (name == NULL)
        return NC_EBADNAME;

    /* check NC_EBADTYPE */
    status = nc3_cktype(nc->mode, type);
    if(status != NC_NOERR)
	return status;

    if(memtype == NC_NAT) memtype = type;

    if(memtype != NC_CHAR && type == NC_CHAR)
	return NC_ECHAR;
    if(memtype == NC_CHAR && type != NC_CHAR)
	return NC_ECHAR;

    /* cast needed for braindead systems with signed size_t */
    if((unsigned long) nelems > X_INT_MAX) /* backward compat */
	return NC_EINVAL; /* Invalid nelems */

    if(nelems != 0 && value == NULL)
	return NC_EINVAL; /* Null arg */

    /* Temporarily removed to preserve extant
       workflows (NCO based and others). See

       https://github.com/Unidata/netcdf-c/issues/843

       for more information. */

#if 0
    if (varid != NC_GLOBAL && !strcmp(name, _FillValue)) {
        /* Fill value must be of the same data type */
        if (type != ncp->vars.value[varid]->type) return NC_EBADTYPE;

        /* Fill value must have exactly one value */
        if (nelems != 1) return NC_EINVAL;

        /* Only allow for variables defined in initial define mode */
        if (ncp->old != NULL && varid < ncp->old->vars.nelems)
            return NC_ELATEFILL; /* try put attribute for an old variable */
    }
#endif

    attrpp = NC_findattr(ncap, name);

    /* 4 cases: exists X indef */

    status = NC3_inq_default_fill_value(type, &fill);
    if (status != NC_NOERR) return status;

    if(attrpp != NULL) { /* name in use */
        if(!NC_indef(ncp)) {
	    const size_t xsz = ncx_len_NC_attrV(type, nelems);
            attrp = *attrpp; /* convenience */

	    if(xsz > attrp->xsz) return NC_ENOTINDEFINE;
	    /* else, we can reuse existing without redef */

	    attrp->xsz = xsz;
            attrp->type = type;
            attrp->nelems = nelems;

            if(nelems != 0) {
                void *xp = attrp->xvalue;
                /* for CDF-1 and CDF-2, NC_BYTE is treated the same type as uchar memtype */
                if (!fIsSet(ncp->flags,NC_64BIT_DATA) && type == NC_BYTE && memtype == NC_UBYTE) {
                    status = NC3_inq_default_fill_value(NC_UBYTE, &fill);
                    if (status != NC_NOERR) return status;
                    status = dispatchput(&xp, nelems, value, memtype, memtype, &fill);
                } else
                    status = dispatchput(&xp, nelems, value, type, memtype, &fill);
            }

            set_NC_hdirty(ncp);

            if(NC_doHsync(ncp)) {
	        const int lstatus = NC_sync(ncp);
                /*
                 * N.B.: potentially overrides NC_ERANGE
                 * set by ncx_pad_putn_I$1
                 */
                if(lstatus != NC_NOERR) return lstatus;
            }

            return status;
        }
        /* else, redefine using existing array slot */
        old = *attrpp;
    } else {
        if(!NC_indef(ncp)) return NC_ENOTINDEFINE;
    }

    status = NC_check_name(name);
    if(status != NC_NOERR) return status;

    attrp = new_NC_attr(name, type, nelems);
    if(attrp == NULL) return NC_ENOMEM;

    if(nelems != 0) {
        void *xp = attrp->xvalue;
        /* for CDF-1 and CDF-2, NC_BYTE is treated the same type as uchar memtype */
        if (!fIsSet(ncp->flags,NC_64BIT_DATA) && type == NC_BYTE && memtype == NC_UBYTE) {
            status = NC3_inq_default_fill_value(NC_UBYTE, &fill);
            if (status != NC_NOERR) return status;
            status = dispatchput(&xp, nelems, (const void*)value, memtype, memtype, &fill);
        } else
            status = dispatchput(&xp, nelems, (const void*)value, type, memtype, &fill);
    }

    if(attrpp != NULL) {
        *attrpp = attrp;
	if(old != NULL)
	        free_NC_attr(old);
    } else {
        const int lstatus = incr_NC_attrarray(ncap, attrp);
        /*
         * N.B.: potentially overrides NC_ERANGE
         * set by ncx_pad_putn_I$1
         */
        if(lstatus != NC_NOERR) {
           free_NC_attr(attrp);
           return lstatus;
        }
    }
    return status;
}

int
NC3_get_att(
	int ncid,
	int varid,
	const char *name,
	void *value,
	nc_type memtype)
{
    int status;
    NC *nc;
    NC3_INFO* ncp;
    NC_attr *attrp;
    const void *xp;

    status = NC_check_id(ncid, &nc);
    if(status != NC_NOERR)
	return status;
    ncp = NC3_DATA(nc);

    status = NC_lookupattr(ncid, varid, name, &attrp);
    if(status != NC_NOERR) return status;

    if(attrp->nelems == 0) return NC_NOERR;

    if(memtype == NC_NAT) memtype = attrp->type;

    if(memtype != NC_CHAR && attrp->type == NC_CHAR)
	return NC_ECHAR;
    if(memtype == NC_CHAR && attrp->type != NC_CHAR)
	return NC_ECHAR;

    xp = attrp->xvalue;
    switch (memtype) {
    case NC_CHAR:
        return ncx_pad_getn_text(&xp, attrp->nelems, (char *)value);
    case NC_BYTE:
        return ncx_pad_getn_Ischar(&xp,attrp->nelems,(schar*)value,attrp->type);
    case NC_SHORT:
        return ncx_pad_getn_Ishort(&xp,attrp->nelems,(short*)value,attrp->type);
    case NC_INT:
          return ncx_pad_getn_Iint(&xp,attrp->nelems,(int*)value,attrp->type);
    case NC_FLOAT:
        return ncx_pad_getn_Ifloat(&xp,attrp->nelems,(float*)value,attrp->type);
    case NC_DOUBLE:
        return ncx_pad_getn_Idouble(&xp,attrp->nelems,(double*)value,attrp->type);
    case NC_INT64:
          return ncx_pad_getn_Ilonglong(&xp,attrp->nelems,(longlong*)value,attrp->type);
    case NC_UBYTE: /* Synthetic */
        /* for CDF-1 and CDF-2, NC_BYTE is treated the same type as uchar memtype */
        if (!fIsSet(ncp->flags,NC_64BIT_DATA) && attrp->type == NC_BYTE)
            return ncx_pad_getn_Iuchar(&xp, attrp->nelems, (uchar *)value, NC_UBYTE);
        else
            return ncx_pad_getn_Iuchar(&xp, attrp->nelems, (uchar *)value, attrp->type);
    case NC_USHORT:
          return ncx_pad_getn_Iushort(&xp,attrp->nelems,(ushort*)value,attrp->type);
    case NC_UINT:
          return ncx_pad_getn_Iuint(&xp,attrp->nelems,(uint*)value,attrp->type);
    case NC_UINT64:
          return ncx_pad_getn_Iulonglong(&xp,attrp->nelems,(ulonglong*)value,attrp->type);
    case NC_NAT:
        return NC_EBADTYPE;
    default:
        break;
    }
    status =  NC_EBADTYPE;
    return status;
}
