1 /** \file
2 The V2 API Functions.
3 
4 Copyright 1996, University Corporation for Atmospheric Research
5 See \ref copyright file for copying and redistribution conditions.
6  */
7 
8 #ifndef NO_NETCDF_2
9 
10 #include "config.h"
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include "xxxnetcdf.h"
15 #include "math.h"
16 /* The subroutines in error.c emit no messages unless NC_VERBOSE bit
17  * is on.  They call exit() when NC_FATAL bit is on. */
18 int ncopts = (NC_FATAL | NC_VERBOSE) ;
19 int ncerr = NC_NOERR ;
20 
21 #if SIZEOF_LONG == SIZEOF_SIZE_T
22 /*
23  * We don't have to copy the arguments to switch from 'long'
24  * to 'size_t' or 'ptrdiff_t'. Use dummy macros.
25  */
26 
27 # define NDIMS_DECL
28 # define A_DECL(name, type, ndims, rhs) \
29 	const type *const name = ((const type *)(rhs))
30 
31 # define A_FREE(name)
32 
33 # define A_INIT(lhs, type, ndims, rhs)
34 
35 #else
36 /*
37  * We do have to copy the arguments to switch from 'long'
38  * to 'size_t' or 'ptrdiff_t'. In my tests on an SGI,
39  * any additional cost was lost in measurement variation.
40  *
41  * This stanza is true on Windows with MinGW-64
42  */
43 
44 # include "onstack.h"
45 
46 static int
nvdims(int ncid,int varid)47 nvdims(int ncid, int varid)
48 {
49    int ndims=-1, status;
50 
51    if ((status = nc_inq_varndims(ncid, varid, &ndims)))
52    {
53       nc_advise("ncvdims", status, "ncid %d", ncid);
54       return -1;
55    }
56    return ndims;
57 }
58 
59 /* Used to avoid errors on 64-bit windows related to
60    c89 macros and flow control/conditionals. */
nvmalloc(off_t size)61 static void* nvmalloc(off_t size) {
62   if(size < 0)
63     return NULL;
64 
65   return malloc(size);
66 
67 }
68 
69 #define NDIMS_DECL const int ndims = nvdims(ncid, varid); \
70 
71 
72 # define A_DECL(name, type, ndims, rhs)		\
73   type *const name = (type*) nvmalloc((ndims) * sizeof(type))
74 
75 
76 #if 0
77   ALLOC_ONSTACK(name, type, ndims)
78 #endif
79 
80 # define A_FREE(name) \
81 	FREE_ONSTACK(name)
82 
83 # define A_INIT(lhs, type, ndims, rhs) \
84 	{ \
85 	  if((off_t)ndims >= 0) {     \
86 		const long *lp = rhs; \
87 		type *tp = lhs; \
88 		type *const end = lhs + ndims; \
89 		while(tp < end) \
90 		{ \
91 			*tp++ = (type) *lp++; \
92 		} \
93 		} \
94 	} \
95 	\
96     if ((off_t)ndims < 0) {nc_advise("nvdims",NC_EMAXDIMS,"ndims %d",ndims); return -1;}
97 
98 
99 #endif
100 
101 typedef signed char schar;
102 
103 /*
104  * Computes number of record variables in an open netCDF file, and an array of
105  * the record variable ids, if the array parameter is non-null.
106  */
107 static int
numrecvars(int ncid,int * nrecvarsp,int * recvarids)108 numrecvars(int ncid, int* nrecvarsp, int *recvarids)
109 {
110     int status = NC_NOERR;
111     int nvars = 0;
112     int ndims = 0;
113     int nrecvars = 0;
114     int varid;
115     int recdimid;
116     int dimids[MAX_NC_DIMS];
117 
118     status = nc_inq_nvars(ncid, &nvars);
119     if(status != NC_NOERR)
120 	return status;
121 
122     status = nc_inq_unlimdim(ncid, &recdimid);
123     if(status != NC_NOERR)
124 	return status;
125 
126     if (recdimid == -1) {
127 	*nrecvarsp = 0;
128 	return NC_NOERR;
129     }
130     nrecvars = 0;
131     for (varid = 0; varid < nvars; varid++) {
132 	status = nc_inq_varndims(ncid, varid, &ndims);
133 	if(status != NC_NOERR)
134 	    return status;
135 	status = nc_inq_vardimid(ncid, varid, dimids);
136 	if(status != NC_NOERR)
137 	    return status;
138 	if (ndims > 0 && dimids[0] == recdimid) {
139 	    if (recvarids != NULL)
140 	      recvarids[nrecvars] = varid;
141 	    nrecvars++;
142 	}
143     }
144     *nrecvarsp = nrecvars;
145     return NC_NOERR;
146 }
147 
148 
149 /*
150  * Computes record size (in bytes) of the record variable with a specified
151  * variable id.  Returns size as 0 if not a record variable.
152  */
153 static int
ncrecsize(int ncid,int varid,size_t * recsizep)154 ncrecsize(int ncid, int varid, size_t *recsizep)
155 {
156     int status = NC_NOERR;
157     int recdimid;
158     nc_type type;
159     int ndims;
160     int dimids[MAX_NC_DIMS];
161     int id;
162     int size;
163 
164     *recsizep = 0;
165     status = nc_inq_unlimdim(ncid, &recdimid);
166     if(status != NC_NOERR)
167 	return status;
168     status = nc_inq_vartype(ncid, varid, &type);
169     if(status != NC_NOERR)
170 	return status;
171     status = nc_inq_varndims(ncid, varid, &ndims);
172     if(status != NC_NOERR)
173 	return status;
174     status = nc_inq_vardimid(ncid, varid, dimids);
175     if(status != NC_NOERR)
176 	return status;
177     if (ndims == 0 || dimids[0] != recdimid) {
178 	return NC_NOERR;
179     }
180     size = nctypelen(type);
181     for (id = 1; id < ndims; id++) {
182 	size_t len;
183 	status = nc_inq_dimlen(ncid, dimids[id], &len);
184 	if(status != NC_NOERR)
185 		return status;
186 	size *= (int)len;
187     }
188     *recsizep = (size_t)size;
189     return NC_NOERR;
190 }
191 
192 
193 /*
194  * Retrieves the dimension sizes of a variable with a specified variable id in
195  * an open netCDF file.  Returns -1 on error.
196  */
197 static int
dimsizes(int ncid,int varid,size_t * sizes)198 dimsizes(int ncid, int varid, size_t *sizes)
199 {
200     int status = NC_NOERR;
201     int ndims;
202     int id;
203     int dimids[MAX_NC_DIMS];
204 
205     status = nc_inq_varndims(ncid, varid, &ndims);
206     if(status != NC_NOERR)
207 	return status;
208     status = nc_inq_vardimid(ncid, varid, dimids);
209     if(status != NC_NOERR)
210 	return status;
211     if (ndims == 0 || sizes == NULL)
212       return NC_NOERR;
213     for (id = 0; id < ndims; id++) {
214 	size_t len;
215 	status = nc_inq_dimlen(ncid, dimids[id], &len);
216 	if(status != NC_NOERR)
217 		return status;
218 	sizes[id] = len;
219     }
220     return NC_NOERR;
221 }
222 
223 
224 /*
225  * Retrieves the number of record variables, the record variable ids, and the
226  * record size of each record variable.  If any pointer to info to be returned
227  * is null, the associated information is not returned.  Returns -1 on error.
228  */
229 int
nc_inq_rec(int ncid,size_t * nrecvarsp,int * recvarids,size_t * recsizes)230 nc_inq_rec(
231 	int ncid,
232 	size_t *nrecvarsp,
233 	int *recvarids,
234 	size_t *recsizes)
235 {
236     int status = NC_NOERR;
237     int nvars = 0;
238     int recdimid;
239     int varid;
240     int rvarids[MAX_NC_VARS];
241     int nrvars = 0;
242 
243     status = nc_inq_nvars(ncid, &nvars);
244     if(status != NC_NOERR)
245 	return status;
246 
247     status = nc_inq_unlimdim(ncid, &recdimid);
248     if(status != NC_NOERR)
249 	return status;
250 
251     if (recdimid == -1)
252 	return NC_NOERR;
253 
254     status = numrecvars(ncid, &nrvars, rvarids);
255     if(status != NC_NOERR)
256 	return status;
257 
258     if (nrecvarsp != NULL)
259 	*nrecvarsp = (size_t)nrvars;
260 
261     if (recvarids != NULL)
262 	for (varid = 0; varid < nrvars; varid++)
263 	    recvarids[varid] = rvarids[varid];
264 
265     if (recsizes != NULL)
266 	for (varid = 0; varid < nrvars; varid++) {
267 	    size_t rsize;
268 	    status = ncrecsize(ncid, rvarids[varid], &rsize);
269 	    if (status != NC_NOERR)
270 		return status;
271 	    recsizes[varid] = rsize;
272 	}
273 	return NC_NOERR;
274 }
275 
276 
277 /*
278  * Write one record's worth of data, except don't write to variables for which
279  * the address of the data to be written is NULL.  Return -1 on error.  This is
280  * the same as the ncrecput() in the library, except that can handle errors
281  * better.
282  */
283 int
nc_put_rec(int ncid,size_t recnum,void * const * datap)284 nc_put_rec(
285 	int ncid,
286 	size_t recnum,
287 	void* const* datap)
288 {
289     int status = NC_NOERR;
290     int varid;
291     int rvarids[MAX_NC_VARS];
292     int nrvars;
293     size_t start[MAX_NC_DIMS];
294     size_t edges[MAX_NC_DIMS];
295 
296     status = numrecvars(ncid, &nrvars, rvarids);
297     if(status != NC_NOERR)
298 	return status;
299 
300     if (nrvars == 0)
301       return NC_NOERR;
302 
303     start[0] = recnum;
304     for (varid = 1; varid < nrvars; varid++)
305 	start[varid] = 0;
306 
307     for (varid = 0; varid < nrvars; varid++) {
308 	if (datap[varid] != NULL) {
309 	    status = dimsizes(ncid, rvarids[varid], edges);
310 	    if(status != NC_NOERR)
311 		return status;
312 
313 	    edges[0] = 1;		/* only 1 record's worth */
314 	    status = nc_put_vara(ncid, rvarids[varid], start, edges, datap[varid]);
315 	    if(status != NC_NOERR)
316 		return status;
317 	}
318     }
319     return 0;
320 }
321 
322 
323 /*
324  * Read one record's worth of data, except don't read from variables for which
325  * the address of the data to be read is null.  Return -1 on error.  This is
326  * the same as the ncrecget() in the library, except that can handle errors
327  * better.
328  */
329 int
nc_get_rec(int ncid,size_t recnum,void ** datap)330 nc_get_rec(
331 	int ncid,
332 	size_t recnum,
333 	void **datap)
334 {
335     int status = NC_NOERR;
336     int varid;
337     int rvarids[MAX_NC_VARS];
338     int nrvars;
339     size_t start[MAX_NC_DIMS];
340     size_t edges[MAX_NC_DIMS];
341 
342     status = numrecvars(ncid, &nrvars, rvarids);
343     if(status != NC_NOERR)
344 	return status;
345 
346     if (nrvars == 0)
347       return NC_NOERR;
348 
349     start[0] = recnum;
350     for (varid = 1; varid < nrvars; varid++)
351 	start[varid] = 0;
352 
353     for (varid = 0; varid < nrvars; varid++) {
354 	if (datap[varid] != NULL) {
355 	    status = dimsizes(ncid, rvarids[varid], edges);
356 	    if(status != NC_NOERR)
357 		return status;
358 	    edges[0] = 1;		/* only 1 record's worth */
359 	    status = nc_get_vara(ncid, rvarids[varid], start, edges, datap[varid]);
360 	    if(status != NC_NOERR)
361 		return status;
362 	}
363     }
364     return 0;
365 }
366 
367 /*
368  */
369 void
nc_advise(const char * routine_name,int err,const char * fmt,...)370 nc_advise(const char *routine_name, int err, const char *fmt,...)
371 {
372 	va_list args;
373 
374 	if(NC_ISSYSERR(err))
375 		ncerr = NC_SYSERR;
376 	else
377 		ncerr = err;
378 
379 	if( ncopts & NC_VERBOSE )
380 	{
381 		(void) fprintf(stderr,"%s: ", routine_name);
382 		va_start(args ,fmt);
383 		(void) vfprintf(stderr,fmt,args);
384 		va_end(args);
385 		if(err != NC_NOERR)
386 		{
387 			(void) fprintf(stderr,": %s",
388 				nc_strerror(err));
389 		}
390 		(void) fputc('\n',stderr);
391 		(void) fflush(stderr);	/* to ensure log files are current */
392 	}
393 
394 	if( (ncopts & NC_FATAL) && err != NC_NOERR )
395 	{
396 		exit(ncopts);
397 	}
398 }
399 
400 /* End error handling */
401 
402 int
nccreate(const char * path,int cmode)403 nccreate(const char* path, int cmode)
404 {
405 	int ncid;
406 	const int status = nc_create(path, cmode, &ncid);
407 	if(status != NC_NOERR)
408 	{
409 		nc_advise("nccreate", status, "filename \"%s\"", path);
410 		return -1;
411 	}
412 	return ncid;
413 }
414 
415 
416 int
ncopen(const char * path,int mode)417 ncopen(const char *path, int mode)
418 {
419 	int ncid;
420 	const int status = nc_open(path, mode, &ncid);
421 	if(status != NC_NOERR)
422 	{
423 		nc_advise("ncopen", status, "filename \"%s\"", path);
424 		return -1;
425 	}
426 	return ncid;
427 }
428 
429 
430 int
ncredef(int ncid)431 ncredef(int ncid)
432 {
433 	const int status =  nc_redef(ncid);
434 	if(status != NC_NOERR)
435 	{
436 		nc_advise("ncredef", status, "ncid %d", ncid);
437 		return -1;
438 	}
439 	return 0;
440 }
441 
442 
443 int
ncendef(int ncid)444 ncendef(int ncid)
445 {
446 	const int status = nc_enddef(ncid);
447 	if(status != NC_NOERR)
448 	{
449 		nc_advise("ncendef", status, "ncid %d", ncid);
450 		return -1;
451 	}
452 	return 0;
453 }
454 
455 
456 int
ncclose(int ncid)457 ncclose(int ncid)
458 {
459 	const int status = nc_close(ncid);
460 	if(status != NC_NOERR)
461 	{
462 		nc_advise("ncclose", status, "ncid %d", ncid);
463 		return -1;
464 
465 	}
466 	return 0;
467 }
468 
469 
470 int
ncinquire(int ncid,int * ndims,int * nvars,int * natts,int * recdim)471 ncinquire(
472     int		ncid,
473     int*	ndims,
474     int*	nvars,
475     int*	natts,
476     int*	recdim
477 )
478 {
479 	int nd, nv, na;
480 	const int status = nc_inq(ncid, &nd, &nv, &na, recdim);
481 
482 	if(status != NC_NOERR)
483 	{
484 		nc_advise("ncinquire", status, "ncid %d", ncid);
485 		return -1;
486 	}
487 	/* else */
488 
489 	if(ndims != NULL)
490 		*ndims = (int) nd;
491 
492 	if(nvars != NULL)
493 		*nvars = (int) nv;
494 
495 	if(natts != NULL)
496 		*natts = (int) na;
497 
498 	return ncid;
499 }
500 
501 
502 int
ncsync(int ncid)503 ncsync(int ncid)
504 {
505 	const int status = nc_sync(ncid);
506 	if(status != NC_NOERR)
507 	{
508 		nc_advise("ncsync", status, "ncid %d", ncid);
509 		return -1;
510 
511 	}
512 	return 0;
513 }
514 
515 
516 int
ncabort(int ncid)517 ncabort(int ncid)
518 {
519 	const int status = nc_abort(ncid);
520 	if(status != NC_NOERR)
521 	{
522 		nc_advise("ncabort", status, "ncid %d", ncid);
523 		return -1;
524 	}
525 	return 0;
526 }
527 
528 
529 int
ncdimdef(int ncid,const char * name,long length)530 ncdimdef(
531     int		ncid,
532     const char*	name,
533     long	length
534 )
535 {
536 	int dimid;
537 	int status = NC_NOERR;
538 	if(length < 0) {
539 	    status = NC_EDIMSIZE;
540 	    nc_advise("ncdimdef", status, "ncid %d", ncid);
541 	    return -1;
542 	}
543 	status =  nc_def_dim(ncid, name, (size_t)length, &dimid);
544 	if(status != NC_NOERR)
545 	{
546 		nc_advise("ncdimdef", status, "ncid %d", ncid);
547 		return -1;
548 	}
549 	return dimid;
550 }
551 
552 
553 int
ncdimid(int ncid,const char * name)554 ncdimid(int ncid, const char*	name)
555 {
556 	int dimid;
557 	const int status =  nc_inq_dimid(ncid, name, &dimid);
558 	if(status != NC_NOERR)
559 	{
560 		nc_advise("ncdimid", status, "ncid %d", ncid);
561 		return -1;
562 	}
563 	return dimid;
564 }
565 
566 
567 int
ncdiminq(int ncid,int dimid,char * name,long * length)568 ncdiminq(
569     int		ncid,
570     int		dimid,
571     char*	name,
572     long*	length
573 )
574 {
575 	size_t ll;
576 	const int status = nc_inq_dim(ncid, dimid, name, &ll);
577 
578 	if(status != NC_NOERR)
579 	{
580 		nc_advise("ncdiminq", status, "ncid %d", ncid);
581 		return -1;
582 	}
583 	/* else */
584 
585 	if(length != NULL)
586 		*length = (int) ll;
587 
588 	return dimid;
589 }
590 
591 
592 int
ncdimrename(int ncid,int dimid,const char * name)593 ncdimrename(
594     int		ncid,
595     int		dimid,
596     const char*	name
597 )
598 {
599 	const int status = nc_rename_dim(ncid, dimid, name);
600 	if(status != NC_NOERR)
601 	{
602 		nc_advise("ncdimrename", status, "ncid %d", ncid);
603 		return -1;
604 	}
605 	return dimid;
606 }
607 
608 
609 int
ncvardef(int ncid,const char * name,nc_type datatype,int ndims,const int * dim)610 ncvardef(
611     int		ncid,
612     const char*	name,
613     nc_type	datatype,
614     int		ndims,
615     const int*	dim
616 )
617 {
618 	int varid = -1;
619 	const int status = nc_def_var(ncid, name, datatype, ndims, dim, &varid);
620 	if(status != NC_NOERR)
621 	{
622 		nc_advise("ncvardef", status, "ncid %d", ncid);
623 		return -1;
624 	}
625 	return varid;
626 }
627 
628 
629 int
ncvarid(int ncid,const char * name)630 ncvarid(
631     int		ncid,
632     const char*	name
633 )
634 {
635 	int varid = -1;
636 	const int status = nc_inq_varid(ncid, name, &varid);
637 	if(status != NC_NOERR)
638 	{
639 		nc_advise("ncvarid", status, "ncid %d", ncid);
640 		return -1;
641 	}
642 	return varid;
643 }
644 
645 
646 int
ncvarinq(int ncid,int varid,char * name,nc_type * datatype,int * ndims,int * dim,int * natts)647 ncvarinq(
648     int		ncid,
649     int		varid,
650     char*	name,
651     nc_type*	datatype,
652     int*	ndims,
653     int*	dim,
654     int*	natts
655 )
656 {
657 	int nd, na;
658 	const int status = nc_inq_var(ncid, varid, name, datatype,
659 		 &nd, dim, &na);
660 
661 	if(status != NC_NOERR)
662 	{
663 		nc_advise("ncvarinq", status, "ncid %d", ncid);
664 		return -1;
665 	}
666 	/* else */
667 
668 	if(ndims != NULL)
669 		*ndims = (int) nd;
670 
671 	if(natts != NULL)
672 		*natts = (int) na;
673 
674 	return varid;
675 }
676 
677 
678 int
ncvarput1(int ncid,int varid,const long * index,const void * value)679 ncvarput1(
680     int		ncid,
681     int		varid,
682     const long*	index,
683     const void*	value
684 )
685 {
686 	NDIMS_DECL
687 	A_DECL(coordp, size_t, (size_t)ndims, index);
688 	A_INIT(coordp, size_t, (size_t)ndims, index);
689 	{
690 	const int status = nc_put_var1(ncid, varid, coordp, value);
691 	A_FREE(coordp);
692 	if(status != NC_NOERR)
693 	{
694 		nc_advise("ncvarput1", status, "ncid %d", ncid);
695 		return -1;
696 	}
697 	}
698 	return 0;
699 }
700 
701 
702 int
ncvarget1(int ncid,int varid,const long * index,void * value)703 ncvarget1(
704     int		ncid,
705     int		varid,
706     const long*	index,
707     void*	value
708 )
709 {
710 	NDIMS_DECL
711 	A_DECL(coordp, size_t, ndims, index);
712 	A_INIT(coordp, size_t, ndims, index);
713 	{
714 	const int status = nc_get_var1(ncid, varid, coordp, value);
715 	A_FREE(coordp);
716 	if(status != NC_NOERR)
717 	{
718 		nc_advise("ncdimid", status, "ncid %d", ncid);
719 		return -1;
720 	}
721 	}
722 	return 0;
723 }
724 
725 
726 int
ncvarput(int ncid,int varid,const long * start,const long * count,const void * value)727 ncvarput(
728     int		ncid,
729     int		varid,
730     const long*	start,
731     const long*	count,
732     const void*	value
733 )
734 {
735 	NDIMS_DECL
736 	A_DECL(stp, size_t, ndims, start);
737 	A_DECL(cntp, size_t, ndims, count);
738 	A_INIT(stp, size_t, ndims, start);
739 	A_INIT(cntp, size_t, ndims, count);
740 	{
741 	const int status = nc_put_vara(ncid, varid, stp, cntp, value);
742 	A_FREE(cntp);
743 	A_FREE(stp);
744 	if(status != NC_NOERR)
745 	{
746 		nc_advise("ncvarput", status, "ncid %d", ncid);
747 		return -1;
748 	}
749 	}
750 	return 0;
751 }
752 
753 
754 int
ncvarget(int ncid,int varid,const long * start,const long * count,void * value)755 ncvarget(
756     int		ncid,
757     int		varid,
758     const long*	start,
759     const long*	count,
760     void*	value
761 )
762 {
763 	NDIMS_DECL
764 	A_DECL(stp, size_t, ndims, start);
765 	A_DECL(cntp, size_t, ndims, count);
766 	A_INIT(stp, size_t, ndims, start);
767 	A_INIT(cntp, size_t, ndims, count);
768 	{
769 	const int status = nc_get_vara(ncid, varid, stp, cntp, value);
770 	A_FREE(cntp);
771 	A_FREE(stp);
772 	if(status != NC_NOERR)
773 	{
774 		nc_advise("ncvarget", status, "ncid %d; varid %d", ncid, varid);
775 		return -1;
776 	}
777 	}
778 	return 0;
779 }
780 
781 
782 int
ncvarputs(int ncid,int varid,const long * start,const long * count,const long * stride,const void * value)783 ncvarputs(
784     int		ncid,
785     int		varid,
786     const long*	start,
787     const long*	count,
788     const long*	stride,
789     const void*	value
790 )
791 {
792 	if(stride == NULL)
793 		return ncvarput(ncid, varid, start, count, value);
794 	/* else */
795 	{
796 
797 	NDIMS_DECL
798 	A_DECL(stp, size_t, ndims, start);
799 	A_DECL(cntp, size_t, ndims, count);
800 	A_DECL(strdp, ptrdiff_t, ndims, stride);
801 	A_INIT(stp, size_t, ndims, start);
802 	A_INIT(cntp, size_t, ndims, count);
803 	A_INIT(strdp, ptrdiff_t, ndims, stride);
804 	{
805 	const int status = nc_put_vars(ncid, varid, stp, cntp, strdp, value);
806 	A_FREE(strdp);
807 	A_FREE(cntp);
808 	A_FREE(stp);
809 	if(status != NC_NOERR)
810 	{
811 		nc_advise("ncvarputs", status, "ncid %d", ncid);
812 		return -1;
813 	}
814 	}
815 	return 0;
816 	}
817 }
818 
819 
820 int
ncvargets(int ncid,int varid,const long * start,const long * count,const long * stride,void * value)821 ncvargets(
822     int		ncid,
823     int		varid,
824     const long*	start,
825     const long*	count,
826     const long*	stride,
827     void*	value
828 )
829 {
830 	if(stride == NULL)
831 		return ncvarget(ncid, varid, start, count, value);
832 	/* else */
833 	{
834 	NDIMS_DECL
835 	A_DECL(stp, size_t, ndims, start);
836 	A_DECL(cntp, size_t, ndims, count);
837 	A_DECL(strdp, ptrdiff_t, ndims, stride);
838 	A_INIT(stp, size_t, ndims, start);
839 	A_INIT(cntp, size_t, ndims, count);
840 	A_INIT(strdp, ptrdiff_t, ndims, stride);
841 	{
842 	const int status = nc_get_vars(ncid, varid, stp, cntp, strdp, value);
843 	A_FREE(strdp);
844 	A_FREE(cntp);
845 	A_FREE(stp);
846 	if(status != NC_NOERR)
847 	{
848 		nc_advise("ncvargets", status, "ncid %d", ncid);
849 		return -1;
850 	}
851 	}
852 	return 0;
853 	}
854 }
855 
856 
857 int
ncvarputg(int ncid,int varid,const long * start,const long * count,const long * stride,const long * map,const void * value)858 ncvarputg(
859     int		ncid,
860     int		varid,
861     const long*	start,
862     const long*	count,
863     const long*	stride,
864     const long*	map,
865     const void* value
866 )
867 {
868 	int ndims = 0;
869 	if(map == NULL)
870 		return ncvarputs(ncid, varid, start, count, stride, value);
871 	/* else */
872 	{
873 	ptrdiff_t *imp=NULL;
874 	if (map != NULL) {
875 		int ret = NC_NOERR;
876 		/* make map[ndims-1] number of elements instead of bytes */
877 		int i, el_size;
878 		nc_type type;
879 		ret = nc_inq_varndims(ncid, varid, &ndims);
880 		if(ret) return ret;
881 		ret = nc_inq_vartype(ncid, varid, &type);
882 		if(ret) return ret;
883 				el_size = nctypelen(type);
884 		imp = (ptrdiff_t*) malloc(ndims * sizeof(ptrdiff_t));
885 		for (i=0; i<ndims; i++) imp[i] = map[i] / el_size;
886 	}
887 
888 	{
889 	A_DECL(stp, size_t, ndims, start);
890 	A_DECL(cntp, size_t, ndims, count);
891 	A_DECL(strdp, ptrdiff_t, ndims, stride);
892 	A_INIT(stp, size_t, ndims, start);
893 	A_INIT(cntp, size_t, ndims, count);
894 	A_INIT(strdp, ptrdiff_t, ndims, stride);
895 	{
896 	const int status = nc_put_varm(ncid, varid,
897 			 stp, cntp, strdp, imp, value);
898 	if (imp!=NULL) free(imp);
899 	A_FREE(strdp);
900 	A_FREE(cntp);
901 	A_FREE(stp);
902 	if(status != NC_NOERR)
903 	{
904 		nc_advise("ncvarputg", status, "ncid %d", ncid);
905 		return -1;
906 	}
907 	}
908 	return 0;
909 	}
910 	}
911 }
912 
913 
914 int
ncvargetg(int ncid,int varid,const long * start,const long * count,const long * stride,const long * map,void * value)915 ncvargetg(
916     int		ncid,
917     int		varid,
918     const long*	start,
919     const long*	count,
920     const long*	stride,
921     const long*	map,
922     void*	value
923 )
924 {
925 	int ndims = 0;
926 	if(map == NULL)
927 		return ncvargets(ncid, varid, start, count, stride, value);
928 	/* else */
929 	{
930 	ptrdiff_t *imp=NULL;
931 	if (map != NULL) {
932 		int ret = NC_NOERR;
933 		/* make map[ndims-1] number of elements instead of bytes */
934 		int i, el_size;
935 		nc_type type;
936 		ret = nc_inq_varndims(ncid, varid, &ndims);
937 		if(ret) return ret;
938 		ret = nc_inq_vartype(ncid, varid, &type);
939 		if(ret) return ret;
940 		el_size = nctypelen(type);
941 		imp = (ptrdiff_t*) malloc(ndims * sizeof(ptrdiff_t));
942 		for (i=0; i<ndims; i++) imp[i] = map[i] / el_size;
943 	}
944 
945 	{
946 	A_DECL(stp, size_t, ndims, start);
947 	A_DECL(cntp, size_t, ndims, count);
948 	A_DECL(strdp, ptrdiff_t, ndims, stride);
949 	A_INIT(stp, size_t, ndims, start);
950 	A_INIT(cntp, size_t, ndims, count);
951 	A_INIT(strdp, ptrdiff_t, ndims, stride);
952 	{
953 	const int status = nc_get_varm(ncid, varid,
954 			stp, cntp, strdp, imp, value);
955 	if (imp!=NULL) free(imp);
956 	A_FREE(strdp);
957 	A_FREE(cntp);
958 	A_FREE(stp);
959 	if(status != NC_NOERR)
960 	{
961 		nc_advise("ncvargetg", status, "ncid %d", ncid);
962 		return -1;
963 	}
964 	}
965 	return 0;
966 	}
967 	}
968 }
969 
970 
971 int
ncvarrename(int ncid,int varid,const char * name)972 ncvarrename(
973     int		ncid,
974     int		varid,
975     const char*	name
976 )
977 {
978 	const int status = nc_rename_var(ncid, varid, name);
979 	if(status != NC_NOERR)
980 	{
981 		nc_advise("ncvarrename", status, "ncid %d", ncid);
982 		return -1;
983 	}
984 	return varid;
985 }
986 
987 
988 int
ncattput(int ncid,int varid,const char * name,nc_type datatype,int len,const void * value)989 ncattput(
990     int		ncid,
991     int		varid,
992     const char*	name,
993     nc_type	datatype,
994     int		len,
995     const void*	value
996 )
997 {
998 	const int status = nc_put_att(ncid, varid, name, datatype, len, value);
999 	if(status != NC_NOERR)
1000 	{
1001 		nc_advise("ncattput", status, "ncid %d", ncid);
1002 		return -1;
1003 	}
1004 	return 0;
1005 }
1006 
1007 
1008 int
ncattinq(int ncid,int varid,const char * name,nc_type * datatype,int * len)1009 ncattinq(
1010     int		ncid,
1011     int		varid,
1012     const char*	name,
1013     nc_type*	datatype,
1014     int*	len
1015 )
1016 {
1017 	size_t ll;
1018 	const int status = nc_inq_att(ncid, varid, name, datatype, &ll);
1019 	if(status != NC_NOERR)
1020 	{
1021 		nc_advise("ncattinq", status,
1022 		    "ncid %d; varid %d; attname \"%s\"",
1023 		    ncid, varid, name);
1024 		return -1;
1025 	}
1026 
1027 	if(len != NULL)
1028 		*len = (int) ll;
1029 
1030 	return 1;
1031 
1032 }
1033 
1034 
1035 int
ncattget(int ncid,int varid,const char * name,void * value)1036 ncattget(
1037     int		ncid,
1038     int		varid,
1039     const char*	name,
1040     void*	value
1041 )
1042 {
1043 	const int status = nc_get_att(ncid, varid, name, value);
1044 	if(status != NC_NOERR)
1045 	{
1046 		nc_advise("ncattget", status, "ncid %d", ncid);
1047 		return -1;
1048 	}
1049 	return 1;
1050 }
1051 
1052 
1053 int
ncattcopy(int ncid_in,int varid_in,const char * name,int ncid_out,int varid_out)1054 ncattcopy(
1055     int		ncid_in,
1056     int		varid_in,
1057     const char*	name,
1058     int		ncid_out,
1059     int		varid_out
1060 )
1061 {
1062 	const int status = nc_copy_att(ncid_in, varid_in, name, ncid_out, varid_out);
1063 	if(status != NC_NOERR)
1064 	{
1065 		nc_advise("ncattcopy", status, "%s", name);
1066 		return -1;
1067 	}
1068 	return 0;
1069 }
1070 
1071 
1072 int
ncattname(int ncid,int varid,int attnum,char * name)1073 ncattname(
1074     int		ncid,
1075     int		varid,
1076     int		attnum,
1077     char*	name
1078 )
1079 {
1080 	const int status = nc_inq_attname(ncid, varid, attnum, name);
1081 	if(status != NC_NOERR)
1082 	{
1083 		nc_advise("ncattname", status, "ncid %d", ncid);
1084 		return -1;
1085 	}
1086 	return attnum;
1087 }
1088 
1089 
1090 int
ncattrename(int ncid,int varid,const char * name,const char * newname)1091 ncattrename(
1092     int		ncid,
1093     int		varid,
1094     const char*	name,
1095     const char*	newname
1096 )
1097 {
1098 	const int status = nc_rename_att(ncid, varid, name, newname);
1099 	if(status != NC_NOERR)
1100 	{
1101 		nc_advise("ncattrename", status, "ncid %d", ncid);
1102 		return -1;
1103 	}
1104 	return 1;
1105 }
1106 
1107 
1108 int
ncattdel(int ncid,int varid,const char * name)1109 ncattdel(
1110     int		ncid,
1111     int		varid,
1112     const char*	name
1113 )
1114 {
1115 	 const int status = nc_del_att(ncid, varid, name);
1116 	if(status != NC_NOERR)
1117 	{
1118 		nc_advise("ncattdel", status, "ncid %d", ncid);
1119 		return -1;
1120 	}
1121 	return 1;
1122 }
1123 
1124 #endif /* NO_NETCDF_2 */
1125 
1126 #ifndef NO_NETCDF_2
1127 
1128 int
ncsetfill(int ncid,int fillmode)1129 ncsetfill(
1130     int		ncid,
1131     int		fillmode
1132 )
1133 {
1134 	int oldmode = -1;
1135 	const int status = nc_set_fill(ncid, fillmode, &oldmode);
1136 	if(status != NC_NOERR)
1137 	{
1138 		nc_advise("ncsetfill", status, "ncid %d", ncid);
1139 		return -1;
1140 	}
1141 	return oldmode;
1142 }
1143 
1144 
1145 int
ncrecinq(int ncid,int * nrecvars,int * recvarids,long * recsizes)1146 ncrecinq(
1147     int		ncid,
1148     int*	nrecvars,
1149     int*	recvarids,
1150     long*	recsizes
1151 )
1152 {
1153 	size_t nrv = 0;
1154 	size_t *rs = NULL;
1155 	int status = NC_NOERR;
1156 
1157 	rs = (size_t*)malloc(sizeof(size_t)*NC_MAX_VARS);
1158 	if(rs == NULL)
1159 	    return NC_ENOMEM;
1160 
1161 	status = nc_inq_rec(ncid, &nrv, recvarids, rs);
1162 	if(status != NC_NOERR)
1163 	{
1164 		nc_advise("ncrecinq", status, "ncid %d", ncid);
1165 		if(rs != NULL) free(rs);
1166 		return -1;
1167 	}
1168 
1169 	if(nrecvars != NULL)
1170 		*nrecvars = (int) nrv;
1171 
1172 	if(recsizes != NULL)
1173 	{
1174 		size_t ii;
1175 		for(ii = 0; ii < nrv; ii++)
1176 		{
1177 			recsizes[ii] = (long) rs[ii];
1178 		}
1179 	}
1180 
1181 	if(rs != NULL) free(rs);
1182 
1183 	return (int) nrv;
1184 }
1185 
1186 
1187 int
ncrecget(int ncid,long recnum,void ** datap)1188 ncrecget(
1189     int		ncid,
1190     long	recnum,
1191     void**	datap
1192 )
1193 {
1194 	const int status = nc_get_rec(ncid, (size_t)recnum, datap);
1195 	if(status != NC_NOERR)
1196 	{
1197 		nc_advise("ncrecget", status, "ncid %d", ncid);
1198 		return -1;
1199 	}
1200 	return 0;
1201 }
1202 
1203 
1204 int
ncrecput(int ncid,long recnum,void * const * datap)1205 ncrecput(
1206     int		ncid,
1207     long	recnum,
1208     void* const* datap
1209 )
1210 {
1211 	const int status = nc_put_rec(ncid, (size_t)recnum, datap);
1212 	if(status != NC_NOERR)
1213 	{
1214 		nc_advise("ncrecput", status, "ncid %d", ncid);
1215 		return -1;
1216 	}
1217 	return 0;
1218 }
1219 
1220 #endif /* NO_NETCDF_2 */
1221