⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 v1hpg.c

📁 一个用来实现偏微分方程中网格的计算库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	Copyright 1996, University Corporation for Atmospheric Research *      See netcdf/COPYRIGHT file for copying and redistribution conditions. *//* $Id: v1hpg.c 2501 2007-11-20 02:33:29Z benkirk $ */#include "nc.h"#include <stdlib.h>#include <stdio.h>#include <string.h>#include <assert.h>#include "rnd.h"#include "ncx.h"/* * This module defines the external representation * of the "header" of a netcdf version one file and * the version two variant that uses 64-bit file  * offsets instead of the 32-bit file offsets in version  * one files. * For each of the components of the NC structure, * There are (static) ncx_len_XXX(), v1h_put_XXX() * and v1h_get_XXX() functions. These define the * external representation of the components. * The exported entry points for the whole NC structure * are built up from these. *//* * "magic number" at beginning of file: 0x43444601 (big endian) * assert(sizeof(ncmagic) % X_ALIGN == 0); */static const schar ncmagic[] = {'C', 'D', 'F', 0x02};static const schar ncmagic1[] = {'C', 'D', 'F', 0x01};/* * v1hs == "Version 1 Header Stream" * * The netcdf file version 1 header is * of unknown and potentially unlimited size. * So, we don't know how much to get() on * the initial read. We build a stream, 'v1hs' * on top of ncio to do the header get. */typedef struct v1hs {	ncio *nciop;	off_t offset;	/* argument to nciop->get() */	size_t extent;	/* argument to nciop->get() */	int flags;	/* set to RGN_WRITE for write */        int version;    /* format variant: NC_FORMAT_CLASSIC or NC_FORMAT_64BIT */	void *base;	/* beginning of current buffer */	void *pos;	/* current position in buffer */	void *end;	/* end of current buffer = base + extent */} v1hs;/* * Release the stream, invalidate buffer */static intrel_v1hs(v1hs *gsp){	int status;	if(gsp->offset == OFF_NONE || gsp->base == NULL)		return ENOERR;	status = gsp->nciop->rel(gsp->nciop, gsp->offset,			 gsp->flags == RGN_WRITE ? RGN_MODIFIED : 0);	gsp->end = NULL;	gsp->pos = NULL;	gsp->base = NULL;	return status;}/* * Release the current chunk and get the next one. * Also used for initialization when gsp->base == NULL. */static intfault_v1hs(v1hs *gsp, size_t extent){	int status;	if(gsp->base != NULL)	{		const ptrdiff_t incr = (char *)gsp->pos - (char *)gsp->base;		status = rel_v1hs(gsp);		if(status)			return status;		gsp->offset += incr;	}		if(extent > gsp->extent)		gsp->extent = extent;		status = gsp->nciop->get(gsp->nciop,		 	gsp->offset, gsp->extent,			gsp->flags, &gsp->base);	if(status)		return status;	gsp->pos = gsp->base;	gsp->end = (char *)gsp->base + gsp->extent;	return ENOERR;}/* * Ensure that 'nextread' bytes are available. */static intcheck_v1hs(v1hs *gsp, size_t nextread){#if 0 /* DEBUG */fprintf(stderr, "nextread %lu, remaining %lu\n",	(unsigned long)nextread,	(unsigned long)((char *)gsp->end - (char *)gsp->pos));#endif	if((char *)gsp->pos + nextread <= (char *)gsp->end)		return ENOERR;	return fault_v1hs(gsp, nextread);}/* End v1hs *//* Write a size_t to the header */static intv1h_put_size_t(v1hs *psp, const size_t *sp){	int status = check_v1hs(psp, X_SIZEOF_SIZE_T);	if(status != ENOERR)		return status;	return ncx_put_size_t(&psp->pos, sp);}/* Read a size_t from the header */static intv1h_get_size_t(v1hs *gsp, size_t *sp){	int status = check_v1hs(gsp, X_SIZEOF_SIZE_T);	if(status != ENOERR)		return status;	return ncx_get_size_t((const void **)(&gsp->pos), sp);}/* Begin nc_type */#define X_SIZEOF_NC_TYPE X_SIZEOF_INT/* Write a nc_type to the header */static intv1h_put_nc_type(v1hs *psp, const nc_type *typep){	const int itype = (int) *typep;	int status = check_v1hs(psp, X_SIZEOF_INT);	if(status != ENOERR)		return status;	status =  ncx_put_int_int(psp->pos, &itype);	psp->pos = (void *)((char *)psp->pos + X_SIZEOF_INT);	return status;}/* Read a nc_type from the header */static intv1h_get_nc_type(v1hs *gsp, nc_type *typep){	int type = 0;	int status = check_v1hs(gsp, X_SIZEOF_INT);	if(status != ENOERR)		return status;	status =  ncx_get_int_int(gsp->pos, &type);	gsp->pos = (void *)((char *)gsp->pos + X_SIZEOF_INT);	if(status != ENOERR)		return status;	assert(type == NC_BYTE		|| type == NC_CHAR		|| type == NC_SHORT		|| type == NC_INT		|| type == NC_FLOAT		|| type == NC_DOUBLE);	/* else */	*typep = (nc_type) type;	return ENOERR;}/* End nc_type *//* Begin NCtype (internal tags) */#define X_SIZEOF_NCTYPE X_SIZEOF_INT/* Write a NCtype to the header */static intv1h_put_NCtype(v1hs *psp, NCtype type){	const int itype = (int) type;	int status = check_v1hs(psp, X_SIZEOF_INT);	if(status != ENOERR)		return status;	status = ncx_put_int_int(psp->pos, &itype);	psp->pos = (void *)((char *)psp->pos + X_SIZEOF_INT);	return status;}/* Read a NCtype from the header */static intv1h_get_NCtype(v1hs *gsp, NCtype *typep){	int type = 0;	int status = check_v1hs(gsp, X_SIZEOF_INT);	if(status != ENOERR)		return status;	status =  ncx_get_int_int(gsp->pos, &type);	gsp->pos = (void *)((char *)gsp->pos + X_SIZEOF_INT);	if(status != ENOERR)		return status;	/* else */	*typep = (NCtype) type;	return ENOERR;}/* End NCtype *//* Begin NC_string *//* * How much space will the xdr'd string take. * FormerlyNC_xlen_string(cdfstr) */static size_tncx_len_NC_string(const NC_string *ncstrp){	size_t sz = X_SIZEOF_SIZE_T; /* nchars */	assert(ncstrp != NULL);	if(ncstrp->nchars != 0) 	{#if 0		assert(ncstrp->nchars % X_ALIGN == 0);		sz += ncstrp->nchars;#else		sz += _RNDUP(ncstrp->nchars, X_ALIGN);#endif	}	return sz;}/* Write a NC_string to the header */static intv1h_put_NC_string(v1hs *psp, const NC_string *ncstrp){	int status;#if 0	assert(ncstrp->nchars % X_ALIGN == 0);#endif	status = v1h_put_size_t(psp, &ncstrp->nchars);	if(status != ENOERR)		return status;	status = check_v1hs(psp, _RNDUP(ncstrp->nchars, X_ALIGN));	if(status != ENOERR)		return status;	status = ncx_pad_putn_text(&psp->pos, ncstrp->nchars, ncstrp->cp);	if(status != ENOERR)		return status;	return ENOERR;}/* Read a NC_string from the header */static intv1h_get_NC_string(v1hs *gsp, NC_string **ncstrpp){	int status;	size_t nchars = 0;	NC_string *ncstrp;	status = v1h_get_size_t(gsp, &nchars);	if(status != ENOERR)		return status;	ncstrp = new_NC_string(nchars, NULL);	if(ncstrp == NULL)	{		return NC_ENOMEM;	}#if 0/* assert(ncstrp->nchars == nchars || ncstrp->nchars - nchars < X_ALIGN); */	assert(ncstrp->nchars % X_ALIGN == 0);	status = check_v1hs(gsp, ncstrp->nchars);#else		status = check_v1hs(gsp, _RNDUP(ncstrp->nchars, X_ALIGN));#endif	if(status != ENOERR)		goto unwind_alloc;	status = ncx_pad_getn_text((const void **)(&gsp->pos),		 nchars, ncstrp->cp);	if(status != ENOERR)		goto unwind_alloc;	*ncstrpp = ncstrp;	return ENOERR;unwind_alloc:	free_NC_string(ncstrp);	return status;	}/* End NC_string *//* Begin NC_dim *//* * How much space will the xdr'd dim take. * FormerlyNC_xlen_dim(dpp) */static size_tncx_len_NC_dim(const NC_dim *dimp){	size_t sz;	assert(dimp != NULL);	sz = ncx_len_NC_string(dimp->name);	sz += X_SIZEOF_SIZE_T;	return(sz);}/* Write a NC_dim to the header */static intv1h_put_NC_dim(v1hs *psp, const NC_dim *dimp){	int status;	status = v1h_put_NC_string(psp, dimp->name);	if(status != ENOERR)		return status;	status = v1h_put_size_t(psp, &dimp->size);	if(status != ENOERR)		return status;	return ENOERR;}/* Read a NC_dim from the header */static intv1h_get_NC_dim(v1hs *gsp, NC_dim **dimpp){	int status;	NC_string *ncstrp;	NC_dim *dimp;	status = v1h_get_NC_string(gsp, &ncstrp);	if(status != ENOERR)		return status;	dimp = new_x_NC_dim(ncstrp);	if(dimp == NULL)	{		status = NC_ENOMEM;		goto unwind_name;	}	status = v1h_get_size_t(gsp, &dimp->size);	if(status != ENOERR)	{		free_NC_dim(dimp); /* frees name */		return status;	}	*dimpp = dimp;	return ENOERR;unwind_name:	free_NC_string(ncstrp);	return status;}/* How much space in the header is required for this NC_dimarray? */static size_tncx_len_NC_dimarray(const NC_dimarray *ncap){	size_t xlen = X_SIZEOF_NCTYPE;	/* type */	xlen += X_SIZEOF_SIZE_T;	/* count */	if(ncap == NULL)		return xlen;	/* else */	{		const NC_dim **dpp = (const NC_dim **)ncap->value;		const NC_dim *const *const end = &dpp[ncap->nelems];		for(  /*NADA*/; dpp < end; dpp++)		{			xlen += ncx_len_NC_dim(*dpp);		}	}	return xlen;}/* Write a NC_dimarray to the header */static intv1h_put_NC_dimarray(v1hs *psp, const NC_dimarray *ncap){	int status;	assert(psp != NULL);	if(ncap == NULL#if 1		/* Backward:		 * This clause is for 'byte for byte'		 * backward compatibility.		 * Strickly speaking, it is 'bug for bug'.		 */		|| ncap->nelems == 0#endif		)	{		/*		 * Handle empty netcdf		 */		const size_t nosz = 0;		status = v1h_put_NCtype(psp, NC_UNSPECIFIED);		if(status != ENOERR)			return status;		status = v1h_put_size_t(psp, &nosz);		if(status != ENOERR)			return status;		return ENOERR;	}	/* else */	status = v1h_put_NCtype(psp, NC_DIMENSION);	if(status != ENOERR)		return status;	status = v1h_put_size_t(psp, &ncap->nelems);	if(status != ENOERR)		return status;	{		const NC_dim **dpp = (const NC_dim **)ncap->value;		const NC_dim *const *const end = &dpp[ncap->nelems];		for( /*NADA*/; dpp < end; dpp++)		{			status = v1h_put_NC_dim(psp, *dpp);			if(status)				return status;		}	}	return ENOERR;}/* Read a NC_dimarray from the header */static intv1h_get_NC_dimarray(v1hs *gsp, NC_dimarray *ncap){	int status;	NCtype type = NC_UNSPECIFIED;	assert(gsp != NULL && gsp->pos != NULL);	assert(ncap != NULL);	assert(ncap->value == NULL);	status = v1h_get_NCtype(gsp, &type);	if(status != ENOERR)		return status;	status = v1h_get_size_t(gsp, &ncap->nelems);	if(status != ENOERR)		return status;		if(ncap->nelems == 0)		return ENOERR;	/* else */	if(type != NC_DIMENSION)		return EINVAL;	ncap->value = (NC_dim **) malloc(ncap->nelems * sizeof(NC_dim *));	if(ncap->value == NULL)		return NC_ENOMEM;	ncap->nalloc = ncap->nelems;	{		NC_dim **dpp = ncap->value;		NC_dim *const *const end = &dpp[ncap->nelems];		for( /*NADA*/; dpp < end; dpp++)		{			status = v1h_get_NC_dim(gsp, dpp);			if(status)			{				ncap->nelems = (size_t)(dpp - ncap->value);				free_NC_dimarrayV(ncap);				return status;			}		}	}	return ENOERR;}/* End NC_dim *//* Begin NC_attr *//* * How much space will 'attrp' take in external representation? * FormerlyNC_xlen_attr(app) */static size_tncx_len_NC_attr(const NC_attr *attrp){	size_t sz;	assert(attrp != NULL);	sz = ncx_len_NC_string(attrp->name);	sz += X_SIZEOF_NC_TYPE; /* type */	sz += X_SIZEOF_SIZE_T; /* nelems */	sz += attrp->xsz;	return(sz);}#undef MIN#define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))/* * Put the values of an attribute * The loop is necessary since attrp->nelems * could potentially be quite large. */static intv1h_put_NC_attrV(v1hs *psp, const NC_attr *attrp){	int status;	const size_t perchunk =  psp->extent;	size_t remaining = attrp->xsz;	void *value = attrp->xvalue;	size_t nbytes; 	assert(psp->extent % X_ALIGN == 0);		do {		nbytes = MIN(perchunk, remaining);			status = check_v1hs(psp, nbytes);		if(status != ENOERR)			return status;			(void) memcpy(psp->pos, value, nbytes);		psp->pos = (void *)((char *)psp->pos + nbytes);		value = (void *)((char *)value + nbytes);		remaining -= nbytes;	} while(remaining != 0); 	return ENOERR;}/* Write a NC_attr to the header */static intv1h_put_NC_attr(v1hs *psp, const NC_attr *attrp){	int status;	status = v1h_put_NC_string(psp, attrp->name);	if(status != ENOERR)		return status;	status = v1h_put_nc_type(psp, &attrp->type);	if(status != ENOERR)		return status;	status = v1h_put_size_t(psp, &attrp->nelems);	if(status != ENOERR)		return status;	status = v1h_put_NC_attrV(psp, attrp);	if(status != ENOERR)		return status;	return ENOERR;}/* * Get the values of an attribute * The loop is necessary since attrp->nelems * could potentially be quite large. */static intv1h_get_NC_attrV(v1hs *gsp, NC_attr *attrp){	int status;	const size_t perchunk =  gsp->extent;	size_t remaining = attrp->xsz;	void *value = attrp->xvalue;	size_t nget; 	do {		nget = MIN(perchunk, remaining);			status = check_v1hs(gsp, nget);		if(status != ENOERR)			return status;			(void) memcpy(value, gsp->pos, nget);		gsp->pos = (void *)((char *)gsp->pos + nget);		value = (void *)((char *)value + nget);		remaining -= nget;	} while(remaining != 0); 	return ENOERR;}/* Read a NC_attr from the header */static intv1h_get_NC_attr(v1hs *gsp, NC_attr **attrpp){	NC_string *strp;	int status;	nc_type type;	size_t nelems;	NC_attr *attrp;	status = v1h_get_NC_string(gsp, &strp);	if(status != ENOERR)		return status;	status = v1h_get_nc_type(gsp, &type);	if(status != ENOERR)		goto unwind_name;	status = v1h_get_size_t(gsp, &nelems);	if(status != ENOERR)		goto unwind_name;	attrp = new_x_NC_attr(strp, type, nelems);	if(attrp == NULL)	{		status = NC_ENOMEM;		goto unwind_name;	}		status = v1h_get_NC_attrV(gsp, attrp);	if(status != ENOERR)	{		free_NC_attr(attrp); /* frees strp */		return status;	}	*attrpp = attrp;	return ENOERR;unwind_name:	free_NC_string(strp);	return status;}/* How much space in the header is required for this NC_attrarray? */static size_tncx_len_NC_attrarray(const NC_attrarray *ncap){	size_t xlen = X_SIZEOF_NCTYPE;	/* type */	xlen += X_SIZEOF_SIZE_T;	/* count */	if(ncap == NULL)		return xlen;	/* else */	{		const NC_attr **app = (const NC_attr **)ncap->value;		const NC_attr *const *const end = &app[ncap->nelems];		for( /*NADA*/; app < end; app++)		{			xlen += ncx_len_NC_attr(*app);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -