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 "netcdf.h"
15 #include <math.h>
16
17 /** \defgroup v2_api The Version 2 API
18
19 NetCDF's modern history began with the introduction of the V2 netCDF
20 API by Glenn Davis and Russ Rew in 1991. (The V1 API is lost to mists
21 of time.)
22
23 The V2 API is still fully supported, but should not be used for new
24 development.
25
26 All of the V2 functions have been reimplemented in terms of the V3 API
27 code; see the documentation for the related V3 functions to get more
28 documentation.
29
30 The V2 API is tested in test directory nctest.
31 */
32
33 /** The subroutines in error.c emit no messages unless NC_VERBOSE bit
34 * is on. They call exit() when NC_FATAL bit is on. */
35 int ncopts = (NC_FATAL | NC_VERBOSE) ;
36
37 int ncerr = NC_NOERR ; /**< V2 API error code. */
38
39 #if SIZEOF_LONG == SIZEOF_SIZE_T
40 /*
41 * We don't have to copy the arguments to switch from 'long'
42 * to 'size_t' or 'ptrdiff_t'. Use dummy macros.
43 */
44
45 # define NDIMS_DECL /**< NDIMS declaration */
46
47 /** @internal Declaration. */
48 # define A_DECL(name, type, ndims, rhs) \
49 const type *const name = ((const type *)(rhs))
50
51 # define A_FREE(name) /**< Free a variable. */
52
53 # define A_INIT(lhs, type, ndims, rhs) /**< Init a variable */
54
55 #else
56 /*
57 * We do have to copy the arguments to switch from 'long'
58 * to 'size_t' or 'ptrdiff_t'. In my tests on an SGI,
59 * any additional cost was lost in measurement variation.
60 *
61 * This stanza is true on Windows with MinGW-64
62 */
63
64 # include "onstack.h"
65
66 static int
nvdims(int ncid,int varid)67 nvdims(int ncid, int varid)
68 {
69 int ndims=-1, status;
70
71 if ((status = nc_inq_varndims(ncid, varid, &ndims)))
72 {
73 nc_advise("ncvdims", status, "ncid %d", ncid);
74 return -1;
75 }
76 return ndims;
77 }
78
79 /* Used to avoid errors on 64-bit windows related to
80 c89 macros and flow control/conditionals. */
nvmalloc(off_t size)81 static void* nvmalloc(off_t size) {
82 if(size < 0)
83 return NULL;
84
85 return malloc(size);
86
87 }
88
89 #define NDIMS_DECL const int ndims = nvdims(ncid, varid); \
90
91
92 # define A_DECL(name, type, ndims, rhs) \
93 type *const name = (type*) nvmalloc((ndims) * sizeof(type))
94
95
96 #if 0
97 ALLOC_ONSTACK(name, type, ndims)
98 #endif
99
100 # define A_FREE(name) \
101 FREE_ONSTACK(name)
102
103 # define A_INIT(lhs, type, ndims, rhs) \
104 { \
105 if((off_t)ndims >= 0) { \
106 const long *lp = rhs; \
107 type *tp = lhs; \
108 type *const end = lhs + ndims; \
109 while(tp < end) \
110 { \
111 *tp++ = (type) *lp++; \
112 } \
113 } \
114 } \
115 \
116 if ((off_t)ndims < 0) {nc_advise("nvdims",NC_EMAXDIMS,"ndims %d",ndims); return -1;}
117
118
119 #endif
120
121 typedef signed char schar; /**< Signed character type. */
122
123 /**
124 * Computes number of record variables in an open netCDF file, and an array of
125 * the record variable ids, if the array parameter is non-null.
126 *
127 * @param ncid File ID.
128 * @param nrecvarsp Pointer that gets number of record variables.
129 * @param recvarids Pointer that gets array of record variable IDs.
130 *
131 * @return ::NC_NOERR No error.
132 * @return -1 on error.
133 * @author Russ Rew
134 */
135 static int
numrecvars(int ncid,int * nrecvarsp,int * recvarids)136 numrecvars(int ncid, int* nrecvarsp, int *recvarids)
137 {
138 int status = NC_NOERR;
139 int nvars = 0;
140 int ndims = 0;
141 int nrecvars = 0;
142 int varid;
143 int recdimid;
144 int dimids[MAX_NC_DIMS];
145
146 status = nc_inq_nvars(ncid, &nvars);
147 if(status != NC_NOERR)
148 return status;
149
150 status = nc_inq_unlimdim(ncid, &recdimid);
151 if(status != NC_NOERR)
152 return status;
153
154 if (recdimid == -1) {
155 *nrecvarsp = 0;
156 return NC_NOERR;
157 }
158 nrecvars = 0;
159 for (varid = 0; varid < nvars; varid++) {
160 status = nc_inq_varndims(ncid, varid, &ndims);
161 if(status != NC_NOERR)
162 return status;
163 status = nc_inq_vardimid(ncid, varid, dimids);
164 if(status != NC_NOERR)
165 return status;
166 if (ndims > 0 && dimids[0] == recdimid) {
167 if (recvarids != NULL)
168 recvarids[nrecvars] = varid;
169 nrecvars++;
170 }
171 }
172 *nrecvarsp = nrecvars;
173 return NC_NOERR;
174 }
175
176
177 /**
178 * Computes record size (in bytes) of the record variable with a specified
179 * variable id. Returns size as 0 if not a record variable.
180 *
181 * @param ncid File ID.
182 * @param varid Variable ID.
183 * @param recsizep Pointer that gets record size.
184 *
185 * @return size, or 0 if not a record variable
186 */
187 static int
ncrecsize(int ncid,int varid,size_t * recsizep)188 ncrecsize(int ncid, int varid, size_t *recsizep)
189 {
190 int status = NC_NOERR;
191 int recdimid;
192 nc_type type;
193 int ndims;
194 int dimids[MAX_NC_DIMS];
195 int id;
196 int size;
197
198 *recsizep = 0;
199 status = nc_inq_unlimdim(ncid, &recdimid);
200 if(status != NC_NOERR)
201 return status;
202 status = nc_inq_vartype(ncid, varid, &type);
203 if(status != NC_NOERR)
204 return status;
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 || dimids[0] != recdimid) {
212 return NC_NOERR;
213 }
214 size = nctypelen(type);
215 for (id = 1; id < ndims; id++) {
216 size_t len;
217 status = nc_inq_dimlen(ncid, dimids[id], &len);
218 if(status != NC_NOERR)
219 return status;
220 size *= (int)len;
221 }
222 *recsizep = (size_t)size;
223 return NC_NOERR;
224 }
225
226
227 /**
228 * Retrieves the dimension sizes of a variable with a specified variable id in
229 * an open netCDF file.
230 *
231 * @param ncid File ID.
232 * @param varid Variable ID.
233 * @param sizes Pointer that gets sizes.
234 *
235 * @return ::NC_NOERR No error.
236 * @return -1 on error.
237 * @author Russ Rew
238 */
239 static int
dimsizes(int ncid,int varid,size_t * sizes)240 dimsizes(int ncid, int varid, size_t *sizes)
241 {
242 int status = NC_NOERR;
243 int ndims;
244 int id;
245 int dimids[MAX_NC_DIMS];
246
247 status = nc_inq_varndims(ncid, varid, &ndims);
248 if(status != NC_NOERR)
249 return status;
250 status = nc_inq_vardimid(ncid, varid, dimids);
251 if(status != NC_NOERR)
252 return status;
253 if (ndims == 0 || sizes == NULL)
254 return NC_NOERR;
255 for (id = 0; id < ndims; id++) {
256 size_t len;
257 status = nc_inq_dimlen(ncid, dimids[id], &len);
258 if(status != NC_NOERR)
259 return status;
260 sizes[id] = len;
261 }
262 return NC_NOERR;
263 }
264
265 /** \ingroup v2_api
266
267 Retrieves the number of record variables, the record variable ids, and the
268 record size of each record variable. If any pointer to info to be returned
269 is null, the associated information is not returned. Returns -1 on error.
270
271 This is part of the legacy V2 API of netCDF. New code should be
272 written with the V3 API. See V3 functions nc_inq_nvars(),
273 nc_inq_unlimdim(), nc_inq_dim().
274
275 \param ncid file ID
276 \param nrecvarsp pointer that will get the number of record variables
277 in the file.
278 \param recvarids pointer to array that will get the variable IDs of
279 all variables that use the record dimension.
280 \param recsizes pointer to array that will dimension size of the
281 record dimension for each variable.
282
283 \returns ::NC_NOERR No error.
284 \returns ::NC_EBADID Bad ncid.
285 \returns ::NC_ENOTVAR Invalid variable ID.
286 \returns ::NC_EINVAL Invalid input
287 */
288 int
nc_inq_rec(int ncid,size_t * nrecvarsp,int * recvarids,size_t * recsizes)289 nc_inq_rec(
290 int ncid,
291 size_t *nrecvarsp,
292 int *recvarids,
293 size_t *recsizes)
294 {
295 int status = NC_NOERR;
296 int nvars = 0;
297 int recdimid;
298 int varid;
299 int rvarids[MAX_NC_VARS];
300 int nrvars = 0;
301
302 status = nc_inq_nvars(ncid, &nvars);
303 if(status != NC_NOERR)
304 return status;
305
306 status = nc_inq_unlimdim(ncid, &recdimid);
307 if(status != NC_NOERR)
308 return status;
309
310 if (recdimid == -1)
311 return NC_NOERR;
312
313 status = numrecvars(ncid, &nrvars, rvarids);
314 if(status != NC_NOERR)
315 return status;
316
317 if (nrecvarsp != NULL)
318 *nrecvarsp = (size_t)nrvars;
319
320 if (recvarids != NULL)
321 for (varid = 0; varid < nrvars; varid++)
322 recvarids[varid] = rvarids[varid];
323
324 if (recsizes != NULL)
325 for (varid = 0; varid < nrvars; varid++) {
326 size_t rsize;
327 status = ncrecsize(ncid, rvarids[varid], &rsize);
328 if (status != NC_NOERR)
329 return status;
330 recsizes[varid] = rsize;
331 }
332 return NC_NOERR;
333 }
334
335 /** \ingroup v2_api
336
337 Write one record's worth of data, except don't write to variables for which
338 the address of the data to be written is NULL. Return -1 on error. This is
339 the same as the ncrecput() in the library, except that can handle errors
340 better.
341
342 This is part of the legacy V2 API of netCDF. New code should be
343 written with the V3 API. See V3 function nc_put_vara().
344
345 \param ncid file ID
346 \param recnum the record number to write.
347 \param datap pointer to one record's worth of data for all variables.
348
349 \returns ::NC_NOERR No error.
350 \returns ::NC_EBADID Bad ncid.
351 \returns ::NC_ENOTVAR Invalid variable ID.
352 \returns ::NC_EINVAL Invalid input
353 */
354 int
nc_put_rec(int ncid,size_t recnum,void * const * datap)355 nc_put_rec(
356 int ncid,
357 size_t recnum,
358 void* const* datap)
359 {
360 int status = NC_NOERR;
361 int varid;
362 int rvarids[MAX_NC_VARS];
363 int nrvars;
364 size_t start[MAX_NC_DIMS];
365 size_t edges[MAX_NC_DIMS];
366
367 status = numrecvars(ncid, &nrvars, rvarids);
368 if(status != NC_NOERR)
369 return status;
370
371 if (nrvars == 0)
372 return NC_NOERR;
373
374 start[0] = recnum;
375 for (varid = 1; varid < nrvars; varid++)
376 start[varid] = 0;
377
378 for (varid = 0; varid < nrvars; varid++) {
379 if (datap[varid] != NULL) {
380 status = dimsizes(ncid, rvarids[varid], edges);
381 if(status != NC_NOERR)
382 return status;
383
384 edges[0] = 1; /* only 1 record's worth */
385 status = nc_put_vara(ncid, rvarids[varid], start, edges, datap[varid]);
386 if(status != NC_NOERR)
387 return status;
388 }
389 }
390 return 0;
391 }
392
393
394 /** \ingroup v2_api
395
396 Read one record's worth of data, except don't read from variables for which
397 the address of the data to be read is null. Return -1 on error. This is
398 the same as the ncrecget() in the library, except that can handle errors
399 better.
400
401 This is part of the legacy V2 API of netCDF. New code should be
402 written with the V3 API. See V3 function nc_get_vara().
403
404 \param ncid file ID
405 \param recnum the record number to read.
406 \param datap pointer memory to hold one record's worth of data for all
407 variables.
408
409 \returns ::NC_NOERR No error.
410 \returns ::NC_EBADID Bad ncid.
411 \returns ::NC_ENOTVAR Invalid variable ID.
412 \returns ::NC_EINVAL Invalid input
413
414 */
415 int
nc_get_rec(int ncid,size_t recnum,void ** datap)416 nc_get_rec(
417 int ncid,
418 size_t recnum,
419 void **datap)
420 {
421 int status = NC_NOERR;
422 int varid;
423 int rvarids[MAX_NC_VARS];
424 int nrvars;
425 size_t start[MAX_NC_DIMS];
426 size_t edges[MAX_NC_DIMS];
427
428 status = numrecvars(ncid, &nrvars, rvarids);
429 if(status != NC_NOERR)
430 return status;
431
432 if (nrvars == 0)
433 return NC_NOERR;
434
435 start[0] = recnum;
436 for (varid = 1; varid < nrvars; varid++)
437 start[varid] = 0;
438
439 for (varid = 0; varid < nrvars; varid++) {
440 if (datap[varid] != NULL) {
441 status = dimsizes(ncid, rvarids[varid], edges);
442 if(status != NC_NOERR)
443 return status;
444 edges[0] = 1; /* only 1 record's worth */
445 status = nc_get_vara(ncid, rvarids[varid], start, edges, datap[varid]);
446 if(status != NC_NOERR)
447 return status;
448 }
449 }
450 return 0;
451 }
452
453 /** \ingroup v2_api
454
455 Show an error message and exit (based on ncopts).
456
457 This is part of the legacy V2 API of netCDF. New code should be
458 written with the V3 API. See V3 function nc_strerror()
459
460 \param routine_name
461 \param err error code
462 \param fmt pointer to a char array containing string format
463
464 */
465 void
nc_advise(const char * routine_name,int err,const char * fmt,...)466 nc_advise(const char *routine_name, int err, const char *fmt,...)
467 {
468 va_list args;
469
470 if(NC_ISSYSERR(err))
471 ncerr = NC_SYSERR;
472 else
473 ncerr = err;
474
475 if( ncopts & NC_VERBOSE )
476 {
477 (void) fprintf(stderr,"%s: ", routine_name);
478 va_start(args ,fmt);
479 (void) vfprintf(stderr,fmt,args);
480 va_end(args);
481 if(err != NC_NOERR)
482 {
483 (void) fprintf(stderr,": %s",
484 nc_strerror(err));
485 }
486 (void) fputc('\n',stderr);
487 (void) fflush(stderr); /* to ensure log files are current */
488 }
489
490 if( (ncopts & NC_FATAL) && err != NC_NOERR )
491 {
492 exit(ncopts);
493 }
494 }
495
496 /* End error handling */
497
498 /** \ingroup v2_api
499
500 Create a netCDF file.
501
502 This is part of the legacy V2 API of netCDF. New code should be
503 written with the V3 API. See V3 function nc_create().
504
505 \param path path and filename of the file to be created.
506 \param cmode see nc_create() for full discussion of the create mode.
507
508 \returns the ncid of the created file.
509 */
510 int
nccreate(const char * path,int cmode)511 nccreate(const char* path, int cmode)
512 {
513 int ncid;
514 const int status = nc_create(path, cmode, &ncid);
515 if(status != NC_NOERR)
516 {
517 nc_advise("nccreate", status, "filename \"%s\"", path);
518 return -1;
519 }
520 return ncid;
521 }
522
523 /** \ingroup v2_api
524
525 Open a netCDF file.
526
527 This is part of the legacy V2 API of netCDF. New code should be
528 written with the V3 API. See V3 function nc_open().
529
530 \param path path and filename of the file to be created.
531 \param mode see nc_open() for full discussion of the open mode.
532
533 \returns the ncid of the created file.
534 */
535 int
ncopen(const char * path,int mode)536 ncopen(const char *path, int mode)
537 {
538 int ncid;
539 const int status = nc_open(path, mode, &ncid);
540 if(status != NC_NOERR)
541 {
542 nc_advise("ncopen", status, "filename \"%s\"", path);
543 return -1;
544 }
545 return ncid;
546 }
547
548 /** \ingroup v2_api
549
550 Put file in define mode.
551
552 This is part of the legacy V2 API of netCDF. New code should be
553 written with the V3 API. See V3 function nc_redef().
554
555 \param ncid file ID
556
557 \returns 0 for success, -1 for failure.
558 */
559 int
ncredef(int ncid)560 ncredef(int ncid)
561 {
562 const int status = nc_redef(ncid);
563 if(status != NC_NOERR)
564 {
565 nc_advise("ncredef", status, "ncid %d", ncid);
566 return -1;
567 }
568 return 0;
569 }
570
571 /** \ingroup v2_api
572
573 End define mode for file.
574
575 This is part of the legacy V2 API of netCDF. New code should be
576 written with the V3 API. See V3 function nc_enddef().
577
578 \param ncid file ID
579
580 \returns 0 for success, -1 for failure.
581 */
582 int
ncendef(int ncid)583 ncendef(int ncid)
584 {
585 const int status = nc_enddef(ncid);
586 if(status != NC_NOERR)
587 {
588 nc_advise("ncendef", status, "ncid %d", ncid);
589 return -1;
590 }
591 return 0;
592 }
593
594 /** \ingroup v2_api
595
596 Close a file.
597
598 This is part of the legacy V2 API of netCDF. New code should be
599 written with the V3 API. See V3 function nc_close().
600
601 \param ncid file ID
602
603 \returns 0 for success, -1 for failure.
604 */
605 int
ncclose(int ncid)606 ncclose(int ncid)
607 {
608 const int status = nc_close(ncid);
609 if(status != NC_NOERR)
610 {
611 nc_advise("ncclose", status, "ncid %d", ncid);
612 return -1;
613
614 }
615 return 0;
616 }
617
618 /** \ingroup v2_api
619
620 Learn about a file.
621
622 This is part of the legacy V2 API of netCDF. New code should be
623 written with the V3 API. See V3 function nc_inq().
624
625 \param ncid file ID
626 \param ndims pointer that will get number of dimensions.
627 \param nvars pointer that will get number of variables.
628 \param natts pointer that will get number of global attributes.
629 \param recdim pointer that will get dimension ID of record dimension,
630 or -1 if there is no record dimension.
631
632 \returns 0 for success, -1 for failure.
633 */
634 int
ncinquire(int ncid,int * ndims,int * nvars,int * natts,int * recdim)635 ncinquire(
636 int ncid,
637 int* ndims,
638 int* nvars,
639 int* natts,
640 int* recdim
641 )
642 {
643 int nd, nv, na;
644 const int status = nc_inq(ncid, &nd, &nv, &na, recdim);
645
646 if(status != NC_NOERR)
647 {
648 nc_advise("ncinquire", status, "ncid %d", ncid);
649 return -1;
650 }
651 /* else */
652
653 if(ndims != NULL)
654 *ndims = (int) nd;
655
656 if(nvars != NULL)
657 *nvars = (int) nv;
658
659 if(natts != NULL)
660 *natts = (int) na;
661
662 return ncid;
663 }
664
665 /** \ingroup v2_api
666
667 Sync a file.
668
669 This is part of the legacy V2 API of netCDF. New code should be
670 written with the V3 API. See V3 function nc_sync().
671
672 \param ncid file ID
673
674 \returns 0 for success, -1 for failure.
675 */
676 int
ncsync(int ncid)677 ncsync(int ncid)
678 {
679 const int status = nc_sync(ncid);
680 if(status != NC_NOERR)
681 {
682 nc_advise("ncsync", status, "ncid %d", ncid);
683 return -1;
684
685 }
686 return 0;
687 }
688
689 /** \ingroup v2_api
690
691 Abort defining a file.
692
693 This is part of the legacy V2 API of netCDF. New code should be
694 written with the V3 API. See V3 function nc_abort().
695
696 \param ncid file ID
697 \returns 0 for success, -1 for failure.
698 */
699 int
ncabort(int ncid)700 ncabort(int ncid)
701 {
702 const int status = nc_abort(ncid);
703 if(status != NC_NOERR)
704 {
705 nc_advise("ncabort", status, "ncid %d", ncid);
706 return -1;
707 }
708 return 0;
709 }
710
711 /** \ingroup v2_api
712
713 Define a dimension.
714
715 This is part of the legacy V2 API of netCDF. New code should be
716 written with the V3 API. See V3 function nc_def_dim().
717
718 \param ncid file ID
719 \param name name of dimension.
720 \param length length of the dimension, NC_UNLIMITED for a record
721 dimension.
722
723 \returns dimid or -1 for failure.
724 */
725 int
ncdimdef(int ncid,const char * name,long length)726 ncdimdef(
727 int ncid,
728 const char* name,
729 long length
730 )
731 {
732 int dimid;
733 int status = NC_NOERR;
734 if(length < 0) {
735 status = NC_EDIMSIZE;
736 nc_advise("ncdimdef", status, "ncid %d", ncid);
737 return -1;
738 }
739 status = nc_def_dim(ncid, name, (size_t)length, &dimid);
740 if(status != NC_NOERR)
741 {
742 nc_advise("ncdimdef", status, "ncid %d", ncid);
743 return -1;
744 }
745 return dimid;
746 }
747
748 /** \ingroup v2_api
749
750 Find dimension ID from name.
751
752 This is part of the legacy V2 API of netCDF. New code should be
753 written with the V3 API. See V3 function nc_inq_dimid().
754
755 \param ncid file ID
756 \param name name of dimension.
757
758 \returns dimid or -1 for failure.
759 */
760 int
ncdimid(int ncid,const char * name)761 ncdimid(int ncid, const char* name)
762 {
763 int dimid;
764 const int status = nc_inq_dimid(ncid, name, &dimid);
765 if(status != NC_NOERR)
766 {
767 nc_advise("ncdimid", status, "ncid %d", ncid);
768 return -1;
769 }
770 return dimid;
771 }
772
773 /** \ingroup v2_api
774
775 Learn about a dimension.
776
777 This is part of the legacy V2 API of netCDF. New code should be
778 written with the V3 API. See V3 function nc_inq_dim().
779
780 \param ncid file ID
781 \param dimid the dimension ID to learn about
782 \param name pointer that will get name of dimension.
783 \param length pointer that will get length of dimension.
784
785 \returns dimid or -1 for failure.
786 */
787 int
ncdiminq(int ncid,int dimid,char * name,long * length)788 ncdiminq(
789 int ncid,
790 int dimid,
791 char* name,
792 long* length
793 )
794 {
795 size_t ll;
796 const int status = nc_inq_dim(ncid, dimid, name, &ll);
797
798 if(status != NC_NOERR)
799 {
800 nc_advise("ncdiminq", status, "ncid %d", ncid);
801 return -1;
802 }
803 /* else */
804
805 if(length != NULL)
806 *length = (int) ll;
807
808 return dimid;
809 }
810
811 /** \ingroup v2_api
812
813 Rename a dimension.
814
815 This is part of the legacy V2 API of netCDF. New code should be
816 written with the V3 API. See V3 function nc_rename_dim().
817
818 \param ncid file ID
819 \param dimid the dimension ID.
820 \param name the new name.
821
822 \returns dimid or -1 for failure.
823 */
824 int
ncdimrename(int ncid,int dimid,const char * name)825 ncdimrename(
826 int ncid,
827 int dimid,
828 const char* name
829 )
830 {
831 const int status = nc_rename_dim(ncid, dimid, name);
832 if(status != NC_NOERR)
833 {
834 nc_advise("ncdimrename", status, "ncid %d", ncid);
835 return -1;
836 }
837 return dimid;
838 }
839
840 /** \ingroup v2_api
841
842 Define a variable.
843
844 This is part of the legacy V2 API of netCDF. New code should be
845 written with the V3 API. See V3 function nc_def_var().
846
847 \param ncid file ID
848 \param name the name of the variable.
849 \param datatype the data type of the variable.
850 \param ndims the number of dimensions.
851 \param dim array of dimension IDs.
852
853 \returns varid or -1 for failure.
854 */
855 int
ncvardef(int ncid,const char * name,nc_type datatype,int ndims,const int * dim)856 ncvardef(
857 int ncid,
858 const char* name,
859 nc_type datatype,
860 int ndims,
861 const int* dim
862 )
863 {
864 int varid = -1;
865 const int status = nc_def_var(ncid, name, datatype, ndims, dim, &varid);
866 if(status != NC_NOERR)
867 {
868 nc_advise("ncvardef", status, "ncid %d", ncid);
869 return -1;
870 }
871 return varid;
872 }
873
874 /** \ingroup v2_api
875
876 Learn a variable ID from the name.
877
878 This is part of the legacy V2 API of netCDF. New code should be
879 written with the V3 API. See V3 function nc_inq_varid().
880
881 \param ncid file ID
882 \param name the name of the variable.
883
884 \returns varid or -1 for failure.
885 */
886 int
ncvarid(int ncid,const char * name)887 ncvarid(
888 int ncid,
889 const char* name
890 )
891 {
892 int varid = -1;
893 const int status = nc_inq_varid(ncid, name, &varid);
894 if(status != NC_NOERR)
895 {
896 nc_advise("ncvarid", status, "ncid %d", ncid);
897 return -1;
898 }
899 return varid;
900 }
901
902 /** \ingroup v2_api
903
904 Learn about a variable.
905
906 This is part of the legacy V2 API of netCDF. New code should be
907 written with the V3 API. See V3 function nc_inq_var().
908
909 \param ncid file ID
910 \param varid the variable ID.
911 \param name pointer to array of char that will get name of variable.
912 \param datatype pointer that will get variable data type.
913 \param ndims pointer that will get number of dimensions.
914 \param dim pointer to array that will get dimension IDs.
915 \param natts pointer that will get number of variable attributes.
916
917 \returns varid or -1 for failure.
918 */
919 int
ncvarinq(int ncid,int varid,char * name,nc_type * datatype,int * ndims,int * dim,int * natts)920 ncvarinq(
921 int ncid,
922 int varid,
923 char* name,
924 nc_type* datatype,
925 int* ndims,
926 int* dim,
927 int* natts
928 )
929 {
930 int nd, na;
931 const int status = nc_inq_var(ncid, varid, name, datatype,
932 &nd, dim, &na);
933
934 if(status != NC_NOERR)
935 {
936 nc_advise("ncvarinq", status, "ncid %d", ncid);
937 return -1;
938 }
939 /* else */
940
941 if(ndims != NULL)
942 *ndims = (int) nd;
943
944 if(natts != NULL)
945 *natts = (int) na;
946
947 return varid;
948 }
949
950 /** \ingroup v2_api
951
952 Write 1 data value.
953
954 This is part of the legacy V2 API of netCDF. New code should be
955 written with the V3 API. See V3 function nc_put_var1().
956
957 \param ncid file ID
958 \param varid the variable ID.
959 \param index pointer to array of index values.
960 \param value pointer to data.
961
962 \returns 0 for success or -1 for failure.
963 */
964 int
ncvarput1(int ncid,int varid,const long * index,const void * value)965 ncvarput1(
966 int ncid,
967 int varid,
968 const long* index,
969 const void* value
970 )
971 {
972 NDIMS_DECL
973 A_DECL(coordp, size_t, (size_t)ndims, index);
974 A_INIT(coordp, size_t, (size_t)ndims, index);
975 {
976 const int status = nc_put_var1(ncid, varid, coordp, value);
977 A_FREE(coordp);
978 if(status != NC_NOERR)
979 {
980 nc_advise("ncvarput1", status, "ncid %d", ncid);
981 return -1;
982 }
983 }
984 return 0;
985 }
986
987 /** \ingroup v2_api
988
989 Read 1 data value.
990
991 This is part of the legacy V2 API of netCDF. New code should be
992 written with the V3 API. See V3 function nc_get_var1().
993
994 \param ncid file ID
995 \param varid the variable ID.
996 \param index pointer to array of index values.
997 \param value pointer that will get data.
998
999 \returns 0 for success or -1 for failure.
1000 */
1001 int
ncvarget1(int ncid,int varid,const long * index,void * value)1002 ncvarget1(
1003 int ncid,
1004 int varid,
1005 const long* index,
1006 void* value
1007 )
1008 {
1009 NDIMS_DECL
1010 A_DECL(coordp, size_t, ndims, index);
1011 A_INIT(coordp, size_t, ndims, index);
1012 {
1013 const int status = nc_get_var1(ncid, varid, coordp, value);
1014 A_FREE(coordp);
1015 if(status != NC_NOERR)
1016 {
1017 nc_advise("ncdimid", status, "ncid %d", ncid);
1018 return -1;
1019 }
1020 }
1021 return 0;
1022 }
1023
1024 /** \ingroup v2_api
1025
1026 Write some data.
1027
1028 This is part of the legacy V2 API of netCDF. New code should be
1029 written with the V3 API. See V3 function nc_put_vara().
1030
1031 \param ncid file ID
1032 \param varid the variable ID.
1033 \param start pointer to array of start values.
1034 \param count pointer to array of count values.
1035 \param value pointer to data.
1036
1037 \returns 0 for success or -1 for failure.
1038 */
1039 int
ncvarput(int ncid,int varid,const long * start,const long * count,const void * value)1040 ncvarput(
1041 int ncid,
1042 int varid,
1043 const long* start,
1044 const long* count,
1045 const void* value
1046 )
1047 {
1048 NDIMS_DECL
1049 A_DECL(stp, size_t, ndims, start);
1050 A_DECL(cntp, size_t, ndims, count);
1051 A_INIT(stp, size_t, ndims, start);
1052 A_INIT(cntp, size_t, ndims, count);
1053 {
1054 const int status = nc_put_vara(ncid, varid, stp, cntp, value);
1055 A_FREE(cntp);
1056 A_FREE(stp);
1057 if(status != NC_NOERR)
1058 {
1059 nc_advise("ncvarput", status, "ncid %d", ncid);
1060 return -1;
1061 }
1062 }
1063 return 0;
1064 }
1065
1066 /** \ingroup v2_api
1067
1068 Read some data.
1069
1070 This is part of the legacy V2 API of netCDF. New code should be
1071 written with the V3 API. See V3 function nc_get_vara().
1072
1073 \param ncid file ID
1074 \param varid the variable ID.
1075 \param start pointer to array of start values.
1076 \param count pointer to array of count values.
1077 \param value pointer to data.
1078
1079 \returns 0 for success or -1 for failure.
1080 */
1081 int
ncvarget(int ncid,int varid,const long * start,const long * count,void * value)1082 ncvarget(
1083 int ncid,
1084 int varid,
1085 const long* start,
1086 const long* count,
1087 void* value
1088 )
1089 {
1090 NDIMS_DECL
1091 A_DECL(stp, size_t, ndims, start);
1092 A_DECL(cntp, size_t, ndims, count);
1093 A_INIT(stp, size_t, ndims, start);
1094 A_INIT(cntp, size_t, ndims, count);
1095 {
1096 const int status = nc_get_vara(ncid, varid, stp, cntp, value);
1097 A_FREE(cntp);
1098 A_FREE(stp);
1099 if(status != NC_NOERR)
1100 {
1101 nc_advise("ncvarget", status, "ncid %d; varid %d", ncid, varid);
1102 return -1;
1103 }
1104 }
1105 return 0;
1106 }
1107
1108 /** \ingroup v2_api
1109
1110 Write strided data.
1111
1112 This is part of the legacy V2 API of netCDF. New code should be
1113 written with the V3 API. See V3 function nc_put_vars().
1114
1115 \param ncid file ID
1116 \param varid the variable ID.
1117 \param start pointer to array of start values.
1118 \param count pointer to array of count values.
1119 \param stride pointer to array of stride values.
1120 \param value pointer to data.
1121
1122 \returns 0 for success or -1 for failure.
1123 */
1124 int
ncvarputs(int ncid,int varid,const long * start,const long * count,const long * stride,const void * value)1125 ncvarputs(
1126 int ncid,
1127 int varid,
1128 const long* start,
1129 const long* count,
1130 const long* stride,
1131 const void* value
1132 )
1133 {
1134 if(stride == NULL)
1135 return ncvarput(ncid, varid, start, count, value);
1136 /* else */
1137 {
1138
1139 NDIMS_DECL
1140 A_DECL(stp, size_t, ndims, start);
1141 A_DECL(cntp, size_t, ndims, count);
1142 A_DECL(strdp, ptrdiff_t, ndims, stride);
1143 A_INIT(stp, size_t, ndims, start);
1144 A_INIT(cntp, size_t, ndims, count);
1145 A_INIT(strdp, ptrdiff_t, ndims, stride);
1146 {
1147 const int status = nc_put_vars(ncid, varid, stp, cntp, strdp, value);
1148 A_FREE(strdp);
1149 A_FREE(cntp);
1150 A_FREE(stp);
1151 if(status != NC_NOERR)
1152 {
1153 nc_advise("ncvarputs", status, "ncid %d", ncid);
1154 return -1;
1155 }
1156 }
1157 return 0;
1158 }
1159 }
1160
1161 /** \ingroup v2_api
1162
1163 Read strided data.
1164
1165 This is part of the legacy V2 API of netCDF. New code should be
1166 written with the V3 API. See V3 function nc_get_vars().
1167
1168 \param ncid file ID
1169 \param varid the variable ID.
1170 \param start pointer to array of start values.
1171 \param count pointer to array of count values.
1172 \param stride pointer to array of stride values.
1173 \param value pointer to data.
1174
1175 \returns 0 for success or -1 for failure.
1176 */
1177 int
ncvargets(int ncid,int varid,const long * start,const long * count,const long * stride,void * value)1178 ncvargets(
1179 int ncid,
1180 int varid,
1181 const long* start,
1182 const long* count,
1183 const long* stride,
1184 void* value
1185 )
1186 {
1187 if(stride == NULL)
1188 return ncvarget(ncid, varid, start, count, value);
1189 /* else */
1190 {
1191 NDIMS_DECL
1192 A_DECL(stp, size_t, ndims, start);
1193 A_DECL(cntp, size_t, ndims, count);
1194 A_DECL(strdp, ptrdiff_t, ndims, stride);
1195 A_INIT(stp, size_t, ndims, start);
1196 A_INIT(cntp, size_t, ndims, count);
1197 A_INIT(strdp, ptrdiff_t, ndims, stride);
1198 {
1199 const int status = nc_get_vars(ncid, varid, stp, cntp, strdp, value);
1200 A_FREE(strdp);
1201 A_FREE(cntp);
1202 A_FREE(stp);
1203 if(status != NC_NOERR)
1204 {
1205 nc_advise("ncvargets", status, "ncid %d", ncid);
1206 return -1;
1207 }
1208 }
1209 return 0;
1210 }
1211 }
1212
1213 /** \ingroup v2_api
1214
1215 Write mapped data.
1216
1217 This is part of the legacy V2 API of netCDF. New code should be
1218 written with the V3 API. See V3 function nc_get_varm().
1219
1220 \param ncid file ID
1221 \param varid the variable ID.
1222 \param start pointer to array of start values.
1223 \param count pointer to array of count values.
1224 \param stride pointer to array of stride values.
1225 \param map pointer to array of map values.
1226 \param value pointer to data.
1227
1228 \returns 0 for success or -1 for failure.
1229 */
1230 int
ncvarputg(int ncid,int varid,const long * start,const long * count,const long * stride,const long * map,const void * value)1231 ncvarputg(
1232 int ncid,
1233 int varid,
1234 const long* start,
1235 const long* count,
1236 const long* stride,
1237 const long* map,
1238 const void* value
1239 )
1240 {
1241 int ndims = 0;
1242 if(map == NULL)
1243 return ncvarputs(ncid, varid, start, count, stride, value);
1244 /* else */
1245 {
1246 ptrdiff_t *imp=NULL;
1247 if (map != NULL) {
1248 int ret = NC_NOERR;
1249 /* make map[ndims-1] number of elements instead of bytes */
1250 int i, el_size;
1251 nc_type type;
1252 ret = nc_inq_varndims(ncid, varid, &ndims);
1253 if(ret) return ret;
1254 ret = nc_inq_vartype(ncid, varid, &type);
1255 if(ret) return ret;
1256 el_size = nctypelen(type);
1257 imp = (ptrdiff_t*) malloc(ndims * sizeof(ptrdiff_t));
1258 for (i=0; i<ndims; i++) imp[i] = map[i] / el_size;
1259 }
1260
1261 {
1262 A_DECL(stp, size_t, ndims, start);
1263 A_DECL(cntp, size_t, ndims, count);
1264 A_DECL(strdp, ptrdiff_t, ndims, stride);
1265 A_INIT(stp, size_t, ndims, start);
1266 A_INIT(cntp, size_t, ndims, count);
1267 A_INIT(strdp, ptrdiff_t, ndims, stride);
1268 {
1269 const int status = nc_put_varm(ncid, varid,
1270 stp, cntp, strdp, imp, value);
1271 if (imp!=NULL) free(imp);
1272 A_FREE(strdp);
1273 A_FREE(cntp);
1274 A_FREE(stp);
1275 if(status != NC_NOERR)
1276 {
1277 nc_advise("ncvarputg", status, "ncid %d", ncid);
1278 return -1;
1279 }
1280 }
1281 return 0;
1282 }
1283 }
1284 }
1285
1286 /** \ingroup v2_api
1287
1288 Read mapped data.
1289
1290 This is part of the legacy V2 API of netCDF. New code should be
1291 written with the V3 API. See V3 function nc_get_varm().
1292
1293 \param ncid file ID
1294 \param varid the variable ID.
1295 \param start pointer to array of start values.
1296 \param count pointer to array of count values.
1297 \param stride pointer to array of stride values.
1298 \param map pointer to array of map values.
1299 \param value pointer to data.
1300
1301 \returns 0 for success or -1 for failure.
1302 */
1303 int
ncvargetg(int ncid,int varid,const long * start,const long * count,const long * stride,const long * map,void * value)1304 ncvargetg(
1305 int ncid,
1306 int varid,
1307 const long* start,
1308 const long* count,
1309 const long* stride,
1310 const long* map,
1311 void* value
1312 )
1313 {
1314 int ndims = 0;
1315 if(map == NULL)
1316 return ncvargets(ncid, varid, start, count, stride, value);
1317 /* else */
1318 {
1319 ptrdiff_t *imp=NULL;
1320 if (map != NULL) {
1321 int ret = NC_NOERR;
1322 /* make map[ndims-1] number of elements instead of bytes */
1323 int i, el_size;
1324 nc_type type;
1325 ret = nc_inq_varndims(ncid, varid, &ndims);
1326 if(ret) return ret;
1327 ret = nc_inq_vartype(ncid, varid, &type);
1328 if(ret) return ret;
1329 el_size = nctypelen(type);
1330 imp = (ptrdiff_t*) malloc(ndims * sizeof(ptrdiff_t));
1331 for (i=0; i<ndims; i++) imp[i] = map[i] / el_size;
1332 }
1333
1334 {
1335 A_DECL(stp, size_t, ndims, start);
1336 A_DECL(cntp, size_t, ndims, count);
1337 A_DECL(strdp, ptrdiff_t, ndims, stride);
1338 A_INIT(stp, size_t, ndims, start);
1339 A_INIT(cntp, size_t, ndims, count);
1340 A_INIT(strdp, ptrdiff_t, ndims, stride);
1341 {
1342 const int status = nc_get_varm(ncid, varid,
1343 stp, cntp, strdp, imp, value);
1344 if (imp!=NULL) free(imp);
1345 A_FREE(strdp);
1346 A_FREE(cntp);
1347 A_FREE(stp);
1348 if(status != NC_NOERR)
1349 {
1350 nc_advise("ncvargetg", status, "ncid %d", ncid);
1351 return -1;
1352 }
1353 }
1354 return 0;
1355 }
1356 }
1357 }
1358
1359 /** \ingroup v2_api
1360
1361 Rename a variable.
1362
1363 This is part of the legacy V2 API of netCDF. New code should be
1364 written with the V3 API. See V3 function nc_rename_var().
1365
1366 \param ncid file ID
1367 \param varid the variable ID.
1368 \param name the new name.
1369
1370 \returns varid or -1 for failure.
1371 */
1372 int
ncvarrename(int ncid,int varid,const char * name)1373 ncvarrename(
1374 int ncid,
1375 int varid,
1376 const char* name
1377 )
1378 {
1379 const int status = nc_rename_var(ncid, varid, name);
1380 if(status != NC_NOERR)
1381 {
1382 nc_advise("ncvarrename", status, "ncid %d", ncid);
1383 return -1;
1384 }
1385 return varid;
1386 }
1387
1388 /** \ingroup v2_api
1389
1390 Write an attribute.
1391
1392 This is part of the legacy V2 API of netCDF. New code should be
1393 written with the V3 API. See V3 function nc_put_att_int(), etc.
1394
1395 \param ncid file ID
1396 \param varid the variable ID or NC_GLOBAL.
1397 \param name the name of the attribute.
1398 \param datatype the type of the attribute.
1399 \param len the length of the attribute.
1400 \param value the attribute value.
1401
1402 \returns dimid or -1 for failure.
1403 */
1404 int
ncattput(int ncid,int varid,const char * name,nc_type datatype,int len,const void * value)1405 ncattput(
1406 int ncid,
1407 int varid,
1408 const char* name,
1409 nc_type datatype,
1410 int len,
1411 const void* value
1412 )
1413 {
1414 const int status = nc_put_att(ncid, varid, name, datatype, len, value);
1415 if(status != NC_NOERR)
1416 {
1417 nc_advise("ncattput", status, "ncid %d", ncid);
1418 return -1;
1419 }
1420 return 0;
1421 }
1422
1423 /** \ingroup v2_api
1424
1425 Learn about an attribute.
1426
1427 This is part of the legacy V2 API of netCDF. New code should be
1428 written with the V3 API. See V3 function nc_inq_att().
1429
1430 \param ncid file ID
1431 \param varid the variable ID.
1432 \param name the name of the attribute.
1433 \param datatype pointer that will get data type.
1434 \param len pointer that will get length.
1435
1436 \returns 1 for success or -1 for failure. (That's a delightful
1437 artifact of a by-gone era of C programming, isn't it?)
1438 */
1439 int
ncattinq(int ncid,int varid,const char * name,nc_type * datatype,int * len)1440 ncattinq(
1441 int ncid,
1442 int varid,
1443 const char* name,
1444 nc_type* datatype,
1445 int* len
1446 )
1447 {
1448 size_t ll;
1449 const int status = nc_inq_att(ncid, varid, name, datatype, &ll);
1450 if(status != NC_NOERR)
1451 {
1452 nc_advise("ncattinq", status,
1453 "ncid %d; varid %d; attname \"%s\"",
1454 ncid, varid, name);
1455 return -1;
1456 }
1457
1458 if(len != NULL)
1459 *len = (int) ll;
1460
1461 return 1;
1462 }
1463
1464 /** \ingroup v2_api
1465
1466 Read an attribute.
1467
1468 This is part of the legacy V2 API of netCDF. New code should be
1469 written with the V3 API. See V3 function nc_get_att_int(), etc.
1470
1471 \param ncid file ID.
1472 \param varid the variable ID or NC_GLOBAL.
1473 \param name the name of the attribute.
1474 \param value pointer that will get the attribute data.
1475
1476 \returns 1 for success or -1 for failure.
1477 */
1478 int
ncattget(int ncid,int varid,const char * name,void * value)1479 ncattget(
1480 int ncid,
1481 int varid,
1482 const char* name,
1483 void* value
1484 )
1485 {
1486 const int status = nc_get_att(ncid, varid, name, value);
1487 if(status != NC_NOERR)
1488 {
1489 nc_advise("ncattget", status, "ncid %d", ncid);
1490 return -1;
1491 }
1492 return 1;
1493 }
1494
1495 /** \ingroup v2_api
1496
1497 Copy an attribute.
1498
1499 This is part of the legacy V2 API of netCDF. New code should be
1500 written with the V3 API. See V3 function nc_get_att_int(), etc.
1501
1502 \param ncid_in file ID to copy from.
1503 \param varid_in the variable ID or NC_GLOBAL to copy from.
1504 \param name the name of the attribute.
1505 \param ncid_out file ID to copy to.
1506 \param varid_out the variable ID or NC_GLOBAL to copy to.
1507
1508 \returns 0 for success or -1 for failure.
1509 */
1510 int
ncattcopy(int ncid_in,int varid_in,const char * name,int ncid_out,int varid_out)1511 ncattcopy(
1512 int ncid_in,
1513 int varid_in,
1514 const char* name,
1515 int ncid_out,
1516 int varid_out
1517 )
1518 {
1519 const int status = nc_copy_att(ncid_in, varid_in, name, ncid_out, varid_out);
1520 if(status != NC_NOERR)
1521 {
1522 nc_advise("ncattcopy", status, "%s", name);
1523 return -1;
1524 }
1525 return 0;
1526 }
1527
1528 /** \ingroup v2_api
1529
1530 Learn attribute name from its number.
1531
1532 This is part of the legacy V2 API of netCDF. New code should be
1533 written with the V3 API. See V3 function nc_inq_attname().
1534
1535 \param ncid file ID
1536 \param varid the variable ID.
1537 \param attnum the number of the attribute.
1538 \param name the name of the attribute.
1539
1540 \returns attnum for success or -1 for failure.
1541 */
1542 int
ncattname(int ncid,int varid,int attnum,char * name)1543 ncattname(
1544 int ncid,
1545 int varid,
1546 int attnum,
1547 char* name
1548 )
1549 {
1550 const int status = nc_inq_attname(ncid, varid, attnum, name);
1551 if(status != NC_NOERR)
1552 {
1553 nc_advise("ncattname", status, "ncid %d", ncid);
1554 return -1;
1555 }
1556 return attnum;
1557 }
1558
1559 /** \ingroup v2_api
1560
1561 Rename an attribute.
1562
1563 This is part of the legacy V2 API of netCDF. New code should be
1564 written with the V3 API. See V3 function nc_rename_att().
1565
1566 \param ncid file ID
1567 \param varid the variable ID.
1568 \param name the attribute name.
1569 \param newname the new name.
1570
1571 \returns 1 for success or -1 for failure.
1572 */
1573 int
ncattrename(int ncid,int varid,const char * name,const char * newname)1574 ncattrename(
1575 int ncid,
1576 int varid,
1577 const char* name,
1578 const char* newname
1579 )
1580 {
1581 const int status = nc_rename_att(ncid, varid, name, newname);
1582 if(status != NC_NOERR)
1583 {
1584 nc_advise("ncattrename", status, "ncid %d", ncid);
1585 return -1;
1586 }
1587 return 1;
1588 }
1589
1590 /** \ingroup v2_api
1591
1592 Delete an attribute.
1593
1594 This is part of the legacy V2 API of netCDF. New code should be
1595 written with the V3 API. See V3 function nc_delete_att().
1596
1597 \param ncid file ID
1598 \param varid the variable ID.
1599 \param name the attribute name.
1600
1601 \returns 1 for success or -1 for failure.
1602 */
1603 int
ncattdel(int ncid,int varid,const char * name)1604 ncattdel(
1605 int ncid,
1606 int varid,
1607 const char* name
1608 )
1609 {
1610 const int status = nc_del_att(ncid, varid, name);
1611 if(status != NC_NOERR)
1612 {
1613 nc_advise("ncattdel", status, "ncid %d", ncid);
1614 return -1;
1615 }
1616 return 1;
1617 }
1618
1619 #endif /* NO_NETCDF_2 */
1620
1621 #ifndef NO_NETCDF_2
1622
1623 /** \ingroup v2_api
1624
1625 Set the fill mode.
1626
1627 This is part of the legacy V2 API of netCDF. New code should be
1628 written with the V3 API. See V3 function nc_set_fill().
1629
1630 \param ncid file ID
1631 \param fillmode NC_FILL or NC_NOFILL.
1632
1633 \returns oldmode for success or -1 for failure.
1634 */
1635 int
ncsetfill(int ncid,int fillmode)1636 ncsetfill(
1637 int ncid,
1638 int fillmode
1639 )
1640 {
1641 int oldmode = -1;
1642 const int status = nc_set_fill(ncid, fillmode, &oldmode);
1643 if(status != NC_NOERR)
1644 {
1645 nc_advise("ncsetfill", status, "ncid %d", ncid);
1646 return -1;
1647 }
1648 return oldmode;
1649 }
1650
1651 /** \ingroup v2_api
1652
1653 Learn record variables and the lengths of the record dimension.
1654
1655 This is part of the legacy V2 API of netCDF. New code should be
1656 written with the V3 API. See V3 functions nc_inq_var()/nc_inq_dim().
1657
1658 \param ncid file ID
1659 \param nrecvars pointer that will get number of record variables.
1660 \param recvarids pointer that will get array of record variable IDs.
1661 \param recsizes pointer that will get array of record dimension length.
1662
1663 \returns oldmode for success or -1 for failure.
1664 */
1665 int
ncrecinq(int ncid,int * nrecvars,int * recvarids,long * recsizes)1666 ncrecinq(
1667 int ncid,
1668 int* nrecvars,
1669 int* recvarids,
1670 long* recsizes
1671 )
1672 {
1673 size_t nrv = 0;
1674 size_t *rs = NULL;
1675 int status = NC_NOERR;
1676
1677 rs = (size_t*)malloc(sizeof(size_t)*NC_MAX_VARS);
1678 if(rs == NULL)
1679 return NC_ENOMEM;
1680
1681 status = nc_inq_rec(ncid, &nrv, recvarids, rs);
1682 if(status != NC_NOERR)
1683 {
1684 nc_advise("ncrecinq", status, "ncid %d", ncid);
1685 if(rs != NULL) free(rs);
1686 return -1;
1687 }
1688
1689 if(nrecvars != NULL)
1690 *nrecvars = (int) nrv;
1691
1692 if(recsizes != NULL)
1693 {
1694 size_t ii;
1695 for(ii = 0; ii < nrv; ii++)
1696 {
1697 recsizes[ii] = (long) rs[ii];
1698 }
1699 }
1700
1701 if(rs != NULL) free(rs);
1702
1703 return (int) nrv;
1704 }
1705
1706 /** \ingroup v2_api
1707
1708 Read one record's worth of data, except don't read from variables for which
1709 the address of the data to be read is null. Return -1 on error. This is
1710 the same as the nc_get_rec(), with poorer error handling.
1711
1712 This is part of the legacy V2 API of netCDF. New code should be
1713 written with the V3 API. See V3 function nc_get_vara().
1714
1715 \param ncid file ID
1716 \param recnum the record number to read.
1717 \param datap pointer memory to hold one record's worth of data for all
1718 variables.
1719
1720 \returns 0 for success, -1 for error.
1721 */
1722 int
ncrecget(int ncid,long recnum,void ** datap)1723 ncrecget(
1724 int ncid,
1725 long recnum,
1726 void** datap
1727 )
1728 {
1729 const int status = nc_get_rec(ncid, (size_t)recnum, datap);
1730 if(status != NC_NOERR)
1731 {
1732 nc_advise("ncrecget", status, "ncid %d", ncid);
1733 return -1;
1734 }
1735 return 0;
1736 }
1737
1738 /** \ingroup v2_api
1739
1740 Write one record's worth of data, except don't write to variables for which
1741 the address of the data to be written is NULL. Return -1 on error. This is
1742 the same as the nc_put_rec(), but with poorer error handling.
1743
1744 This is part of the legacy V2 API of netCDF. New code should be
1745 written with the V3 API. See V3 function nc_put_vara().
1746
1747 \param ncid file ID
1748 \param recnum the record number to write.
1749 \param datap pointer to one record's worth of data for all variables.
1750
1751 \returns 0 for success, -1 for error.
1752 */
1753 int
ncrecput(int ncid,long recnum,void * const * datap)1754 ncrecput(
1755 int ncid,
1756 long recnum,
1757 void* const* datap
1758 )
1759 {
1760 const int status = nc_put_rec(ncid, (size_t)recnum, datap);
1761 if(status != NC_NOERR)
1762 {
1763 nc_advise("ncrecput", status, "ncid %d", ncid);
1764 return -1;
1765 }
1766 return 0;
1767 }
1768
1769 #endif /* NO_NETCDF_2 */
1770