1 /*! \file
2 Functions for getting data from variables.
3 
4 Copyright 2011 University Corporation for Atmospheric
5 Research/Unidata. See \ref copyright file for more info.
6 
7 */
8 
9 #include "ncdispatch.h"
10 
11 #undef VARS_USES_VARM
12 #ifndef VARS_USES_VARM
13 
14 /*!
15   \internal
16 
17 */
18 struct GETodometer {
19     int            rank;
20     size_t         index[NC_MAX_VAR_DIMS];
21     size_t         start[NC_MAX_VAR_DIMS];
22     size_t         edges[NC_MAX_VAR_DIMS];
23     ptrdiff_t      stride[NC_MAX_VAR_DIMS];
24     size_t         stop[NC_MAX_VAR_DIMS];
25 };
26 
27 
28 /** \internal
29 
30  */
31 static void
odom_init(struct GETodometer * odom,int rank,const size_t * start,const size_t * edges,const ptrdiff_t * stride)32 odom_init(struct GETodometer* odom,
33 	    int rank,
34 	    const size_t* start, const size_t* edges, const ptrdiff_t* stride)
35 {
36     int i;
37     memset(odom,0,sizeof(struct GETodometer));
38     odom->rank = rank;
39     assert(odom->rank <= NC_MAX_VAR_DIMS);
40     for(i=0;i<odom->rank;i++) {
41 	odom->start[i] = (start != NULL ? start[i] : 0);
42 	odom->edges[i] = (edges != NULL ? edges[i] : 1);
43 	odom->stride[i] = (stride != NULL ? stride[i] : 1);
44 	odom->stop[i] = odom->start[i] + (odom->edges[i]*((size_t)odom->stride[i]));
45 	odom->index[i] = odom->start[i];
46     }
47 }
48 
49 /** \internal
50 
51  */
52 static int
odom_more(struct GETodometer * odom)53 odom_more(struct GETodometer* odom)
54 {
55     return (odom->index[0] < odom->stop[0]);
56 }
57 
58 /** \internal
59 
60  */
61 static int
odom_next(struct GETodometer * odom)62 odom_next(struct GETodometer* odom)
63 {
64     int i;
65     if(odom->rank == 0) return 0;
66     for(i=odom->rank-1;i>=0;i--) {
67         odom->index[i] += (size_t)odom->stride[i];
68         if(odom->index[i] < odom->stop[i]) break;
69 	if(i == 0) return 0; /* leave the 0th entry if it overflows*/
70 	odom->index[i] = odom->start[i]; /* reset this position*/
71     }
72     return 1;
73 }
74 #endif
75 
76 /** \internal
77 \ingroup variables
78 
79  */
80 int
NC_get_vara(int ncid,int varid,const size_t * start,const size_t * edges,void * value,nc_type memtype)81 NC_get_vara(int ncid, int varid,
82 	    const size_t *start, const size_t *edges,
83             void *value, nc_type memtype)
84 {
85    NC* ncp;
86    int stat = NC_check_id(ncid, &ncp);
87    if(stat != NC_NOERR) return stat;
88 #ifdef USE_NETCDF4
89    if(memtype >= NC_FIRSTUSERTYPEID) memtype = NC_NAT;
90 #endif
91 
92    if(edges == NULL) {
93       size_t shape[NC_MAX_VAR_DIMS];
94       int ndims;
95       stat = nc_inq_varndims(ncid, varid, &ndims);
96       if(stat != NC_NOERR) return stat;
97       stat = NC_getshape(ncid,varid,ndims,shape);
98       if(stat != NC_NOERR) return stat;
99       stat = ncp->dispatch->get_vara(ncid,varid,start,shape,value,memtype);
100    } else
101       stat =  ncp->dispatch->get_vara(ncid,varid,start,edges,value,memtype);
102    return stat;
103 }
104 
105 /** \ingroup variables
106 \internal
107  */
108 static int
NC_get_var(int ncid,int varid,void * value,nc_type memtype)109 NC_get_var(int ncid, int varid, void *value, nc_type memtype)
110 {
111    int ndims;
112    size_t shape[NC_MAX_VAR_DIMS];
113    int stat = nc_inq_varndims(ncid,varid, &ndims);
114    if(stat) return stat;
115    stat = NC_getshape(ncid,varid, ndims, shape);
116    if(stat) return stat;
117    return NC_get_vara(ncid, varid, NC_coord_zero, shape, value, memtype);
118 }
119 
120 /** \internal
121 \ingroup variables
122  Most dispatch tables will use the default procedures
123 */
124 int
NCDEFAULT_get_vars(int ncid,int varid,const size_t * start,const size_t * edges,const ptrdiff_t * stride,void * value0,nc_type memtype)125 NCDEFAULT_get_vars(int ncid, int varid, const size_t * start,
126 	    const size_t * edges, const ptrdiff_t * stride,
127 	    void *value0, nc_type memtype)
128 {
129 #ifdef VARS_USES_VARM
130    NC* ncp;
131    int stat = NC_check_id(ncid, &ncp);
132 
133    if(stat != NC_NOERR) return stat;
134    return ncp->dispatch->get_varm(ncid,varid,start,edges,stride,NULL,value0,memtype);
135 #else
136   /* Rebuilt get_vars code to simplify and avoid use of get_varm */
137 
138    int status = NC_NOERR;
139    int i,simplestride,isrecvar;
140    int rank;
141    struct GETodometer odom;
142    nc_type vartype = NC_NAT;
143    NC* ncp;
144    int memtypelen;
145    size_t vartypelen;
146    size_t nels;
147    char* value = (char*)value0;
148    size_t numrecs;
149    size_t varshape[NC_MAX_VAR_DIMS];
150    size_t mystart[NC_MAX_VAR_DIMS];
151    size_t myedges[NC_MAX_VAR_DIMS];
152    ptrdiff_t mystride[NC_MAX_VAR_DIMS];
153    char *memptr = NULL;
154 
155    status = NC_check_id (ncid, &ncp);
156    if(status != NC_NOERR) return status;
157 
158    status = nc_inq_vartype(ncid, varid, &vartype);
159    if(status != NC_NOERR) return status;
160 
161    if(memtype == NC_NAT) memtype = vartype;
162 
163    /* compute the variable type size */
164    status = nc_inq_type(ncid,vartype,NULL,&vartypelen);
165    if(status != NC_NOERR) return status;
166 
167    if(memtype > NC_MAX_ATOMIC_TYPE)
168 	memtypelen = (int)vartypelen;
169     else
170 	memtypelen = nctypelen(memtype);
171 
172    /* Check gross internal/external type compatibility */
173    if(vartype != memtype) {
174       /* If !atomic, the two types must be the same */
175       if(vartype > NC_MAX_ATOMIC_TYPE
176          || memtype > NC_MAX_ATOMIC_TYPE)
177 	 return NC_EBADTYPE;
178       /* ok, the types differ but both are atomic */
179       if(memtype == NC_CHAR || vartype == NC_CHAR)
180 	 return NC_ECHAR;
181    }
182 
183    /* Get the variable rank */
184    status = nc_inq_varndims(ncid, varid, &rank);
185    if(status != NC_NOERR) return status;
186 
187    /* Get variable dimension sizes */
188    isrecvar = NC_is_recvar(ncid,varid,&numrecs);
189    NC_getshape(ncid,varid,rank,varshape);
190 
191    /* Optimize out using various checks */
192    if (rank == 0) {
193       /*
194        * The variable is a scalar; consequently,
195        * there s only one thing to get and only one place to put it.
196        * (Why was I called?)
197        */
198       size_t edge1[1] = {1};
199       return NC_get_vara(ncid, varid, start, edge1, value, memtype);
200    }
201 
202    /* Do various checks and fixups on start/edges/stride */
203    simplestride = 1; /* assume so */
204    nels = 1;
205    for(i=0;i<rank;i++) {
206 	size_t dimlen;
207 	mystart[i] = (start == NULL ? 0 : start[i]);
208         /* illegal value checks */
209 	dimlen = (i == 0 && isrecvar ? numrecs : varshape[i]);
210         /* mystart is unsigned, never < 0 */
211 #ifdef RELAX_COORD_BOUND
212 	if (mystart[i] > dimlen) return NC_EINVALCOORDS;
213 #else
214 	if (mystart[i] >= dimlen) return NC_EINVALCOORDS;
215 #endif
216 	if(edges == NULL) {
217 	   if(i == 0 && isrecvar)
218   	      myedges[i] = numrecs - start[i];
219 	   else
220 	      myedges[i] = varshape[i] - mystart[i];
221 	} else
222 	    myedges[i] = edges[i];
223 #ifdef RELAX_COORD_BOUND
224 	if (mystart[i] == dimlen && myedges[i] > 0) return NC_EINVALCOORDS;
225 #endif
226         /* myedges is unsigned, never < 0 */
227 	if(mystart[i] + myedges[i] > dimlen)
228 	  return NC_EEDGE;
229 	mystride[i] = (stride == NULL ? 1 : stride[i]);
230 	if(mystride[i] <= 0
231 	   /* cast needed for braindead systems with signed size_t */
232            || ((unsigned long) mystride[i] >= X_INT_MAX))
233            return NC_ESTRIDE;
234   	if(mystride[i] != 1) simplestride = 0;
235         if(myedges[i] == 0)
236           nels = 0;
237    }
238    if(nels == 0)
239       return NC_NOERR; /* cannot read anything */
240    if(simplestride) {
241       return NC_get_vara(ncid, varid, mystart, myedges, value, memtype);
242    }
243 
244    /* memptr indicates where to store the next value */
245    memptr = value;
246 
247    odom_init(&odom,rank,mystart,myedges,mystride);
248 
249    /* walk the odometer to extract values */
250    while(odom_more(&odom)) {
251       int localstatus = NC_NOERR;
252       /* Read a single value */
253       localstatus = NC_get_vara(ncid,varid,odom.index,nc_sizevector1,memptr,memtype);
254       /* So it turns out that when get_varm is used, all errors are
255          delayed and ERANGE will be overwritten by more serious errors.
256       */
257       if(localstatus != NC_NOERR) {
258 	    if(status == NC_NOERR || localstatus != NC_ERANGE)
259 	       status = localstatus;
260       }
261       memptr += memtypelen;
262       odom_next(&odom);
263    }
264    return status;
265 #endif
266 }
267 
268 /** \internal
269 \ingroup variables
270  */
271 static int
NC_get_var1(int ncid,int varid,const size_t * coord,void * value,nc_type memtype)272 NC_get_var1(int ncid, int varid, const size_t *coord, void* value,
273 	    nc_type memtype)
274 {
275    return NC_get_vara(ncid, varid, coord, NC_coord_one, value, memtype);
276 }
277 
278 /** \internal
279 \ingroup variables
280  */
281 int
NCDEFAULT_get_varm(int ncid,int varid,const size_t * start,const size_t * edges,const ptrdiff_t * stride,const ptrdiff_t * imapp,void * value0,nc_type memtype)282 NCDEFAULT_get_varm(int ncid, int varid, const size_t *start,
283 	    const size_t *edges, const ptrdiff_t *stride,
284 	    const ptrdiff_t *imapp, void *value0, nc_type memtype)
285 {
286    int status = NC_NOERR;
287    nc_type vartype = NC_NAT;
288    int varndims,maxidim;
289    NC* ncp;
290    int memtypelen;
291    char* value = (char*)value0;
292 
293    status = NC_check_id (ncid, &ncp);
294    if(status != NC_NOERR) return status;
295 
296 /*
297   if(NC_indef(ncp)) return NC_EINDEFINE;
298 */
299 
300    status = nc_inq_vartype(ncid, varid, &vartype);
301    if(status != NC_NOERR) return status;
302    /* Check that this is an atomic type */
303    if(vartype > NC_MAX_ATOMIC_TYPE)
304 	return NC_EMAPTYPE;
305 
306    status = nc_inq_varndims(ncid, varid, &varndims);
307    if(status != NC_NOERR) return status;
308 
309    if(memtype == NC_NAT) {
310       memtype = vartype;
311    }
312 
313    if(memtype == NC_CHAR && vartype != NC_CHAR)
314       return NC_ECHAR;
315    else if(memtype != NC_CHAR && vartype == NC_CHAR)
316       return NC_ECHAR;
317 
318    memtypelen = nctypelen(memtype);
319 
320    maxidim = (int) varndims - 1;
321 
322    if (maxidim < 0)
323    {
324       /*
325        * The variable is a scalar; consequently,
326        * there s only one thing to get and only one place to put it.
327        * (Why was I called?)
328        */
329       size_t edge1[1] = {1};
330       return NC_get_vara(ncid, varid, start, edge1, value, memtype);
331    }
332 
333    /*
334     * else
335     * The variable is an array.
336     */
337    {
338       int idim;
339       size_t *mystart = NULL;
340       size_t *myedges;
341       size_t *iocount;    /* count vector */
342       size_t *stop;   /* stop indexes */
343       size_t *length; /* edge lengths in bytes */
344       ptrdiff_t *mystride;
345       ptrdiff_t *mymap;
346       size_t varshape[NC_MAX_VAR_DIMS];
347       int isrecvar;
348       size_t numrecs;
349 
350       /* Compute some dimension related values */
351       isrecvar = NC_is_recvar(ncid,varid,&numrecs);
352       NC_getshape(ncid,varid,varndims,varshape);
353 
354       /*
355        * Verify stride argument; also see if stride is all ones
356        */
357       if(stride != NULL) {
358 	 int stride1 = 1;
359 	 for (idim = 0; idim <= maxidim; ++idim)
360 	 {
361             if (stride[idim] == 0
362 		/* cast needed for braindead systems with signed size_t */
363                 || ((unsigned long) stride[idim] >= X_INT_MAX))
364             {
365 	       return NC_ESTRIDE;
366             }
367 	    if(stride[idim] != 1) stride1 = 0;
368 	 }
369          /* If stride1 is true, and there is no imap
370             then call get_vara directly.
371          */
372          if(stride1 && imapp == NULL) {
373 	     return NC_get_vara(ncid, varid, start, edges, value, memtype);
374 	 }
375       }
376 
377       /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
378       /* Allocate space for mystart,mystride,mymap etc.all at once */
379       mystart = (size_t *)calloc((size_t)(varndims * 7), sizeof(ptrdiff_t));
380       if(mystart == NULL) return NC_ENOMEM;
381       myedges = mystart + varndims;
382       iocount = myedges + varndims;
383       stop = iocount + varndims;
384       length = stop + varndims;
385       mystride = (ptrdiff_t *)(length + varndims);
386       mymap = mystride + varndims;
387 
388       /*
389        * Check start, edges
390        */
391       for (idim = maxidim; idim >= 0; --idim)
392       {
393 	 size_t dimlen =
394 	    idim == 0 && isrecvar
395 	    ? numrecs
396 	    : varshape[idim];
397 
398 	 mystart[idim] = start != NULL
399 	    ? start[idim]
400 	    : 0;
401 
402 #ifdef RELAX_COORD_BOUND
403 	 if (mystart[idim] > dimlen)
404 #else
405 	 if (mystart[idim] >= dimlen)
406 #endif
407 	 {
408 	    status = NC_EINVALCOORDS;
409 	    goto done;
410 	 }
411 
412 #ifdef COMPLEX
413 	 myedges[idim] = edges != NULL
414 	    ? edges[idim]
415 	    : idim == 0 && isrecvar
416 	    ? numrecs - mystart[idim]
417 	    : varshape[idim] - mystart[idim];
418 #else
419 	 if(edges != NULL)
420 	    myedges[idim] = edges[idim];
421 	 else if (idim == 0 && isrecvar)
422 	    myedges[idim] = numrecs - mystart[idim];
423 	 else
424 	    myedges[idim] = varshape[idim] - mystart[idim];
425 #endif
426 
427 #ifdef RELAX_COORD_BOUND
428 	 if (mystart[idim] == dimlen && myedges[idim] > 0)
429 	 {
430 	    status = NC_EINVALCOORDS;
431 	    goto done;
432 	 }
433 #endif
434 
435 	 if (mystart[idim] + myedges[idim] > dimlen)
436 	 {
437 	    status = NC_EEDGE;
438 	    goto done;
439 	 }
440       }
441 
442 
443       /*
444        * Initialize I/O parameters.
445        */
446       for (idim = maxidim; idim >= 0; --idim)
447       {
448 	 if (edges != NULL && edges[idim] == 0)
449 	 {
450 	    status = NC_NOERR;    /* read/write no data */
451 	    goto done;
452 	 }
453 
454 	 mystride[idim] = stride != NULL
455 	    ? stride[idim]
456 	    : 1;
457 
458 	 /* Remember: in netCDF-2 imapp is byte oriented, not index oriented
459 	  *           Starting from netCDF-3, imapp is index oriented */
460 #ifdef COMPLEX
461 	 mymap[idim] = (imapp != NULL
462 			? imapp[idim]
463 			: (idim == maxidim ? 1
464 			   : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1]));
465 #else
466 	 if(imapp != NULL)
467 	    mymap[idim] = imapp[idim];
468 	 else if (idim == maxidim)
469 	    mymap[idim] = 1;
470 	 else
471 	    mymap[idim] =
472 	       mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
473 #endif
474 	 iocount[idim] = 1;
475 	 length[idim] = ((size_t)mymap[idim]) * myedges[idim];
476 	 stop[idim] = (mystart[idim] + myedges[idim] * (size_t)mystride[idim]);
477       }
478 
479       /* Lower body */
480       /*
481        * As an optimization, adjust I/O parameters when the fastest
482        * dimension has unity stride both externally and internally.
483        * In this case, the user could have called a simpler routine
484        * (i.e. ncvar$1()
485        */
486       if (mystride[maxidim] == 1
487 	  && mymap[maxidim] == 1)
488       {
489 	 iocount[maxidim] = myedges[maxidim];
490 	 mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
491 	 mymap[maxidim] = (ptrdiff_t) length[maxidim];
492       }
493 
494       /*
495        * Perform I/O.  Exit when done.
496        */
497       for (;;)
498       {
499 	 /* TODO: */
500 	 int lstatus = NC_get_vara(ncid, varid, mystart, iocount,
501 				   value, memtype);
502 	 if (lstatus != NC_NOERR) {
503 	    if(status == NC_NOERR || lstatus != NC_ERANGE)
504 	       status = lstatus;
505 	 }
506 	 /*
507 	  * The following code permutes through the variable s
508 	  * external start-index space and it s internal address
509 	  * space.  At the UPC, this algorithm is commonly
510 	  * called "odometer code".
511 	  */
512 	 idim = maxidim;
513         carry:
514 	 value += (((int)mymap[idim]) * memtypelen);
515 	 mystart[idim] += (size_t)mystride[idim];
516 	 if (mystart[idim] == stop[idim])
517 	 {
518 	    size_t l = (length[idim] * (size_t)memtypelen);
519 	    value -= l;
520 	    mystart[idim] = start[idim];
521 	    if (--idim < 0)
522 	       break; /* normal return */
523 	    goto carry;
524 	 }
525       } /* I/O loop */
526      done:
527       free(mystart);
528    } /* variable is array */
529    return status;
530 }
531 
532 /** \ingroup variables
533 \internal
534 Called by externally visible nc_get_vars_xxx routines */
535 static int
NC_get_vars(int ncid,int varid,const size_t * start,const size_t * edges,const ptrdiff_t * stride,void * value,nc_type memtype)536 NC_get_vars(int ncid, int varid, const size_t *start,
537 	    const size_t *edges, const ptrdiff_t *stride, void *value,
538 	    nc_type memtype)
539 {
540    NC* ncp;
541    int stat = NC_check_id(ncid, &ncp);
542 
543    if(stat != NC_NOERR) return stat;
544 #ifdef USE_NETCDF4
545    if(memtype >= NC_FIRSTUSERTYPEID) memtype = NC_NAT;
546 #endif
547    return ncp->dispatch->get_vars(ncid,varid,start,edges,stride,value,memtype);
548 }
549 
550 /** \ingroup variables
551 \internal
552 Called by externally visible nc_get_varm_xxx routines
553  */
554 static int
NC_get_varm(int ncid,int varid,const size_t * start,const size_t * edges,const ptrdiff_t * stride,const ptrdiff_t * map,void * value,nc_type memtype)555 NC_get_varm(int ncid, int varid, const size_t *start,
556 	    const size_t *edges, const ptrdiff_t *stride, const ptrdiff_t* map,
557 	    void *value, nc_type memtype)
558 {
559    NC* ncp;
560    int stat = NC_check_id(ncid, &ncp);
561 
562    if(stat != NC_NOERR) return stat;
563 #ifdef USE_NETCDF4
564    if(memtype >= NC_FIRSTUSERTYPEID) memtype = NC_NAT;
565 #endif
566    return ncp->dispatch->get_varm(ncid,varid,start,edges,stride,map,value,memtype);
567 }
568 
569 /** \name Reading Data from Variables
570 
571 Functions to read data from variables. */
572 /*! \{ */ /* All these functions are part of this named group... */
573 
574 /** \ingroup variables
575 Read an array of values from a variable.
576 
577 The array to be read is specified by giving a corner and a vector of
578 edge lengths to \ref specify_hyperslab.
579 
580 The data values are read into consecutive locations with the last
581 dimension varying fastest. The netCDF dataset must be in data mode
582 (for netCDF-4/HDF5 files, the switch to data mode will happen
583 automatically, unless the classic model is used).
584 
585 The nc_get_vara() function will read a variable of any type,
586 including user defined type. For this function, the type of the data
587 in memory must match the type of the variable - no data conversion is
588 done.
589 
590 Other nc_get_vara_ functions will convert data to the desired output
591 type as needed.
592 
593 \param ncid NetCDF or group ID, from a previous call to nc_open(),
594 nc_create(), nc_def_grp(), or associated inquiry functions such as
595 nc_inq_ncid().
596 
597 \param varid Variable ID
598 
599 \param startp Start vector with one element for each dimension to \ref
600 specify_hyperslab.
601 
602 \param countp Count vector with one element for each dimension to \ref
603 specify_hyperslab.
604 
605 \param ip Pointer where the data will be copied. Memory must be
606 allocated by the user before this function is called.
607 
608 \returns ::NC_NOERR No error.
609 \returns ::NC_ENOTVAR Variable not found.
610 \returns ::NC_EINVALCOORDS Index exceeds dimension bound.
611 \returns ::NC_EEDGE Start+count exceeds dimension bound.
612 \returns ::NC_ERANGE One or more of the values are out of range.
613 \returns ::NC_EINDEFINE Operation not allowed in define mode.
614 \returns ::NC_EBADID Bad ncid.
615 
616 \section nc_get_vara_double_example Example
617 
618 Here is an example using nc_get_vara_double() to read all the values of
619 the variable named rh from an existing netCDF dataset named
620 foo.nc. For simplicity in this example, we assume that we know that rh
621 is dimensioned with time, lat, and lon, and that there are three time
622 values, five lat values, and ten lon values.
623 
624 \code
625      #include <xxxnetcdf.h>
626         ...
627      #define TIMES 3
628      #define LATS 5
629      #define LONS 10
630      int  status;
631      int ncid;
632      int rh_id;
633      static size_t start[] = {0, 0, 0};
634      static size_t count[] = {TIMES, LATS, LONS};
635      double rh_vals[TIMES*LATS*LONS];
636         ...
637      status = nc_open("foo.nc", NC_NOWRITE, &ncid);
638      if (status != NC_NOERR) handle_error(status);
639         ...
640      status = nc_inq_varid (ncid, "rh", &rh_id);
641      if (status != NC_NOERR) handle_error(status);
642         ...
643      status = nc_get_vara_double(ncid, rh_id, start, count, rh_vals);
644      if (status != NC_NOERR) handle_error(status);
645 \endcode
646  */
647 /**@{*/
648 int
nc_get_vara(int ncid,int varid,const size_t * startp,const size_t * countp,void * ip)649 nc_get_vara(int ncid, int varid, const size_t *startp,
650 	    const size_t *countp, void *ip)
651 {
652    NC* ncp = NULL;
653    nc_type xtype = NC_NAT;
654    int stat = NC_check_id(ncid, &ncp);
655    if(stat != NC_NOERR) return stat;
656    stat = nc_inq_vartype(ncid, varid, &xtype);
657    if(stat != NC_NOERR) return stat;
658    return NC_get_vara(ncid, varid, startp, countp, ip, xtype);
659 }
660 
661 int
nc_get_vara_text(int ncid,int varid,const size_t * startp,const size_t * countp,char * ip)662 nc_get_vara_text(int ncid, int varid, const size_t *startp,
663 		 const size_t *countp, char *ip)
664 {
665    NC* ncp;
666    int stat = NC_check_id(ncid, &ncp);
667    if(stat != NC_NOERR) return stat;
668    return NC_get_vara(ncid, varid, startp, countp,
669 		      (void *)ip, NC_CHAR);
670 }
671 
672 int
nc_get_vara_schar(int ncid,int varid,const size_t * startp,const size_t * countp,signed char * ip)673 nc_get_vara_schar(int ncid, int varid, const size_t *startp,
674 		  const size_t *countp, signed char *ip)
675 {
676    NC* ncp;
677    int stat = NC_check_id(ncid, &ncp);
678    if(stat != NC_NOERR) return stat;
679    return NC_get_vara(ncid, varid, startp, countp,
680 		      (void *)ip, NC_BYTE);
681 }
682 
683 int
nc_get_vara_uchar(int ncid,int varid,const size_t * startp,const size_t * countp,unsigned char * ip)684 nc_get_vara_uchar(int ncid, int varid, const size_t *startp,
685 		  const size_t *countp, unsigned char *ip)
686 {
687    NC* ncp;
688    int stat = NC_check_id(ncid, &ncp);
689    if(stat != NC_NOERR) return stat;
690    return NC_get_vara(ncid, varid, startp, countp,
691 		      (void *)ip, T_uchar);
692 }
693 
694 int
nc_get_vara_short(int ncid,int varid,const size_t * startp,const size_t * countp,short * ip)695 nc_get_vara_short(int ncid, int varid, const size_t *startp,
696 		  const size_t *countp, short *ip)
697 {
698    NC* ncp;
699    int stat = NC_check_id(ncid, &ncp);
700    if(stat != NC_NOERR) return stat;
701    return NC_get_vara(ncid, varid, startp, countp,
702 		      (void *)ip, NC_SHORT);
703 }
704 
705 int
nc_get_vara_int(int ncid,int varid,const size_t * startp,const size_t * countp,int * ip)706 nc_get_vara_int(int ncid, int varid,
707 		const size_t *startp, const size_t *countp, int *ip)
708 {
709    NC* ncp;
710    int stat = NC_check_id(ncid, &ncp);
711    if(stat != NC_NOERR) return stat;
712    return NC_get_vara(ncid,varid,startp,countp, (void *)ip,NC_INT);
713 }
714 
715 int
nc_get_vara_long(int ncid,int varid,const size_t * startp,const size_t * countp,long * ip)716 nc_get_vara_long(int ncid, int varid,
717 		 const size_t *startp, const size_t *countp, long *ip)
718 {
719    NC* ncp;
720    int stat = NC_check_id(ncid, &ncp);
721    if(stat != NC_NOERR) return stat;
722    return NC_get_vara(ncid,varid,startp,countp, (void *)ip,T_long);
723 }
724 
725 int
nc_get_vara_float(int ncid,int varid,const size_t * startp,const size_t * countp,float * ip)726 nc_get_vara_float(int ncid, int varid,
727 		  const size_t *startp, const size_t *countp, float *ip)
728 {
729    NC* ncp;
730    int stat = NC_check_id(ncid, &ncp);
731    if(stat != NC_NOERR) return stat;
732    return NC_get_vara(ncid,varid,startp,countp, (void *)ip,T_float);
733 }
734 
735 
736 int
nc_get_vara_double(int ncid,int varid,const size_t * startp,const size_t * countp,double * ip)737 nc_get_vara_double(int ncid, int varid, const size_t *startp,
738 		   const size_t *countp, double *ip)
739 {
740    NC* ncp;
741    int stat = NC_check_id(ncid, &ncp);
742    if(stat != NC_NOERR) return stat;
743    return NC_get_vara(ncid,varid,startp,countp, (void *)ip,T_double);
744 }
745 
746 int
nc_get_vara_ubyte(int ncid,int varid,const size_t * startp,const size_t * countp,unsigned char * ip)747 nc_get_vara_ubyte(int ncid, int varid,
748 		  const size_t *startp, const size_t *countp, unsigned char *ip)
749 {
750    NC* ncp;
751    int stat = NC_check_id(ncid, &ncp);
752    if(stat != NC_NOERR) return stat;
753    return NC_get_vara(ncid,varid,startp,countp, (void *)ip,T_ubyte);
754 }
755 
756 int
nc_get_vara_ushort(int ncid,int varid,const size_t * startp,const size_t * countp,unsigned short * ip)757 nc_get_vara_ushort(int ncid, int varid,
758 		   const size_t *startp, const size_t *countp, unsigned short *ip)
759 {
760    NC* ncp;
761    int stat = NC_check_id(ncid, &ncp);
762    if(stat != NC_NOERR) return stat;
763    return NC_get_vara(ncid,varid,startp,countp, (void *)ip,T_ushort);
764 }
765 
766 int
nc_get_vara_uint(int ncid,int varid,const size_t * startp,const size_t * countp,unsigned int * ip)767 nc_get_vara_uint(int ncid, int varid,
768 		 const size_t *startp, const size_t *countp, unsigned int *ip)
769 {
770    NC* ncp;
771    int stat = NC_check_id(ncid, &ncp);
772    if(stat != NC_NOERR) return stat;
773    return NC_get_vara(ncid,varid,startp,countp, (void *)ip,T_uint);
774 }
775 
776 int
nc_get_vara_longlong(int ncid,int varid,const size_t * startp,const size_t * countp,long long * ip)777 nc_get_vara_longlong(int ncid, int varid,
778 		     const size_t *startp, const size_t *countp, long long *ip)
779 {
780    NC* ncp;
781    int stat = NC_check_id(ncid, &ncp);
782    if(stat != NC_NOERR) return stat;
783    return NC_get_vara(ncid,varid,startp,countp, (void *)ip,T_longlong);
784 }
785 
786 int
nc_get_vara_ulonglong(int ncid,int varid,const size_t * startp,const size_t * countp,unsigned long long * ip)787 nc_get_vara_ulonglong(int ncid, int varid,
788 		      const size_t *startp, const size_t *countp, unsigned long long *ip)
789 {
790    NC* ncp;
791    int stat = NC_check_id(ncid, &ncp);
792    if(stat != NC_NOERR) return stat;
793    return NC_get_vara(ncid,varid,startp,countp, (void *)ip,NC_UINT64);
794 }
795 
796 #ifdef USE_NETCDF4
797 int
nc_get_vara_string(int ncid,int varid,const size_t * startp,const size_t * countp,char ** ip)798 nc_get_vara_string(int ncid, int varid,
799 		   const size_t *startp, const size_t *countp, char* *ip)
800 {
801    NC* ncp;
802    int stat = NC_check_id(ncid, &ncp);
803    if(stat != NC_NOERR) return stat;
804    return NC_get_vara(ncid,varid,startp,countp, (void *)ip,NC_STRING);
805 }
806 
807 #endif /*USE_NETCDF4*/
808 /**@}*/
809 
810 /** \ingroup variables
811 Read a single datum from a variable.
812 
813 Inputs are the netCDF ID, the variable ID, a multidimensional index
814 that specifies which value to get, and the address of a location into
815 which the data value will be read. The value is converted from the
816 external data type of the variable, if necessary.
817 
818 The nc_get_var1() function will read a variable of any type, including
819 user defined type. For this function, the type of the data in memory
820 must match the type of the variable - no data conversion is done.
821 
822 Other nc_get_var1_ functions will convert data to the desired output
823 type as needed.
824 
825 \param ncid NetCDF or group ID, from a previous call to nc_open(),
826 nc_create(), nc_def_grp(), or associated inquiry functions such as
827 nc_inq_ncid().
828 
829 \param varid Variable ID
830 
831 \param indexp Index vector with one element for each dimension.
832 
833 \param ip Pointer where the data will be copied. Memory must be
834 allocated by the user before this function is called.
835 
836 \returns ::NC_NOERR No error.
837 \returns ::NC_ENOTVAR Variable not found.
838 \returns ::NC_EINVALCOORDS Index exceeds dimension bound.
839 \returns ::NC_ERANGE One or more of the values are out of range.
840 \returns ::NC_EINDEFINE Operation not allowed in define mode.
841 \returns ::NC_EBADID Bad ncid.
842 */
843 /** \{ */
844 int
nc_get_var1(int ncid,int varid,const size_t * indexp,void * ip)845 nc_get_var1(int ncid, int varid, const size_t *indexp, void *ip)
846 {
847    return NC_get_var1(ncid, varid, indexp, ip, NC_NAT);
848 }
849 
850 int
nc_get_var1_text(int ncid,int varid,const size_t * indexp,char * ip)851 nc_get_var1_text(int ncid, int varid, const size_t *indexp, char *ip)
852 {
853    NC* ncp;
854    int stat = NC_check_id(ncid, &ncp);
855    if(stat != NC_NOERR) return stat;
856    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_CHAR);
857 }
858 
859 int
nc_get_var1_schar(int ncid,int varid,const size_t * indexp,signed char * ip)860 nc_get_var1_schar(int ncid, int varid, const size_t *indexp, signed char *ip)
861 {
862    NC* ncp;
863    int stat = NC_check_id(ncid, &ncp);
864    if(stat != NC_NOERR) return stat;
865    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_BYTE);
866 }
867 
868 int
nc_get_var1_uchar(int ncid,int varid,const size_t * indexp,unsigned char * ip)869 nc_get_var1_uchar(int ncid, int varid, const size_t *indexp, unsigned char *ip)
870 {
871    NC* ncp;
872    int stat = NC_check_id(ncid, &ncp);
873    if(stat != NC_NOERR) return stat;
874    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_UBYTE);
875 }
876 
877 int
nc_get_var1_short(int ncid,int varid,const size_t * indexp,short * ip)878 nc_get_var1_short(int ncid, int varid, const size_t *indexp, short *ip)
879 {
880    NC* ncp;
881    int stat = NC_check_id(ncid, &ncp);
882    if(stat != NC_NOERR) return stat;
883    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_SHORT);
884 }
885 
886 int
nc_get_var1_int(int ncid,int varid,const size_t * indexp,int * ip)887 nc_get_var1_int(int ncid, int varid, const size_t *indexp, int *ip)
888 {
889    NC* ncp;
890    int stat = NC_check_id(ncid, &ncp);
891    if(stat != NC_NOERR) return stat;
892    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_INT);
893 }
894 
895 int
nc_get_var1_long(int ncid,int varid,const size_t * indexp,long * ip)896 nc_get_var1_long(int ncid, int varid, const size_t *indexp,
897 		 long *ip)
898 {
899    NC* ncp;
900    int stat = NC_check_id(ncid, &ncp);
901    if(stat != NC_NOERR) return stat;
902    return NC_get_var1(ncid, varid, indexp, (void *)ip, longtype);
903 }
904 
905 int
nc_get_var1_float(int ncid,int varid,const size_t * indexp,float * ip)906 nc_get_var1_float(int ncid, int varid, const size_t *indexp,
907 		  float *ip)
908 {
909    NC* ncp;
910    int stat = NC_check_id(ncid, &ncp);
911    if(stat != NC_NOERR) return stat;
912    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_FLOAT);
913 }
914 
915 int
nc_get_var1_double(int ncid,int varid,const size_t * indexp,double * ip)916 nc_get_var1_double(int ncid, int varid, const size_t *indexp,
917 		   double *ip)
918 {
919    NC* ncp;
920    int stat = NC_check_id(ncid, &ncp);
921    if(stat != NC_NOERR) return stat;
922    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_DOUBLE);
923 }
924 
925 int
nc_get_var1_ubyte(int ncid,int varid,const size_t * indexp,unsigned char * ip)926 nc_get_var1_ubyte(int ncid, int varid, const size_t *indexp,
927 		  unsigned char *ip)
928 {
929    NC* ncp;
930    int stat = NC_check_id(ncid, &ncp);
931    if(stat != NC_NOERR) return stat;
932    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_UBYTE);
933 }
934 
935 int
nc_get_var1_ushort(int ncid,int varid,const size_t * indexp,unsigned short * ip)936 nc_get_var1_ushort(int ncid, int varid, const size_t *indexp,
937 		   unsigned short *ip)
938 {
939    NC* ncp;
940    int stat = NC_check_id(ncid, &ncp);
941    if(stat != NC_NOERR) return stat;
942    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_USHORT);
943 }
944 
945 int
nc_get_var1_uint(int ncid,int varid,const size_t * indexp,unsigned int * ip)946 nc_get_var1_uint(int ncid, int varid, const size_t *indexp,
947 		 unsigned int *ip)
948 {
949    NC* ncp;
950    int stat = NC_check_id(ncid, &ncp);
951    if(stat != NC_NOERR) return stat;
952    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_UINT);
953 }
954 
955 int
nc_get_var1_longlong(int ncid,int varid,const size_t * indexp,long long * ip)956 nc_get_var1_longlong(int ncid, int varid, const size_t *indexp,
957 		     long long *ip)
958 {
959    NC* ncp;
960    int stat = NC_check_id(ncid, &ncp);
961    if(stat != NC_NOERR) return stat;
962    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_INT64);
963 }
964 
965 int
nc_get_var1_ulonglong(int ncid,int varid,const size_t * indexp,unsigned long long * ip)966 nc_get_var1_ulonglong(int ncid, int varid, const size_t *indexp,
967 		      unsigned long long *ip)
968 {
969    NC* ncp;
970    int stat = NC_check_id(ncid, &ncp);
971    if(stat != NC_NOERR) return stat;
972    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_UINT64);
973 }
974 
975 #ifdef USE_NETCDF4
976 int
nc_get_var1_string(int ncid,int varid,const size_t * indexp,char ** ip)977 nc_get_var1_string(int ncid, int varid, const size_t *indexp, char* *ip)
978 {
979    NC* ncp;
980    int stat = NC_check_id(ncid, &ncp);
981    if(stat != NC_NOERR) return stat;
982    return NC_get_var1(ncid, varid, indexp, (void *)ip, NC_STRING);
983 }
984 #endif /*USE_NETCDF4*/
985 /** \} */
986 
987 /** \ingroup variables
988 Read an entire variable in one call.
989 
990 This function will read all the values from a netCDF variable of an
991 open netCDF dataset.
992 
993 This is the simplest interface to use for reading the value of a
994 scalar variable or when all the values of a multidimensional variable
995 can be read at once. The values are read into consecutive locations
996 with the last dimension varying fastest. The netCDF dataset must be in
997 data mode.
998 
999 Take care when using this function with record variables (variables
1000 that use the ::NC_UNLIMITED dimension). If you try to read all the
1001 values of a record variable into an array but there are more records
1002 in the file than you assume, more data will be read than you expect,
1003 which may cause a segmentation violation. To avoid such problems, it
1004 is better to use the nc_get_vara interfaces for variables that use the
1005 ::NC_UNLIMITED dimension.
1006 
1007 The functions for types ubyte, ushort, uint, longlong, ulonglong, and
1008 string are only available for netCDF-4/HDF5 files.
1009 
1010 The nc_get_var() function will read a variable of any type, including
1011 user defined type. For this function, the type of the data in memory
1012 must match the type of the variable - no data conversion is done.
1013 
1014 \param ncid NetCDF or group ID, from a previous call to nc_open(),
1015 nc_create(), nc_def_grp(), or associated inquiry functions such as
1016 nc_inq_ncid().
1017 
1018 \param varid Variable ID
1019 
1020 \param ip Pointer where the data will be copied. Memory must be
1021 allocated by the user before this function is called.
1022 
1023 \returns ::NC_NOERR No error.
1024 \returns ::NC_ENOTVAR Variable not found.
1025 \returns ::NC_ERANGE One or more of the values are out of range.
1026 \returns ::NC_EINDEFINE Operation not allowed in define mode.
1027 \returns ::NC_EBADID Bad ncid.
1028 */
1029 /** \{ */
1030 int
nc_get_var(int ncid,int varid,void * ip)1031 nc_get_var(int ncid, int varid, void *ip)
1032 {
1033    return NC_get_var(ncid, varid, ip, NC_NAT);
1034 }
1035 
1036 int
nc_get_var_text(int ncid,int varid,char * ip)1037 nc_get_var_text(int ncid, int varid, char *ip)
1038 {
1039    NC *ncp;
1040    int stat = NC_check_id(ncid, &ncp);
1041    if(stat != NC_NOERR) return stat;
1042    return NC_get_var(ncid, varid, (void *)ip, NC_CHAR);
1043 }
1044 
1045 int
nc_get_var_schar(int ncid,int varid,signed char * ip)1046 nc_get_var_schar(int ncid, int varid, signed char *ip)
1047 {
1048    NC *ncp;
1049    int stat = NC_check_id(ncid, &ncp);
1050    if(stat != NC_NOERR) return stat;
1051    return NC_get_var(ncid, varid, (void *)ip, NC_BYTE);
1052 }
1053 
1054 int
nc_get_var_uchar(int ncid,int varid,unsigned char * ip)1055 nc_get_var_uchar(int ncid, int varid, unsigned char *ip)
1056 {
1057    NC *ncp;
1058    int stat = NC_check_id(ncid, &ncp);
1059    if(stat != NC_NOERR) return stat;
1060    return NC_get_var(ncid,varid, (void *)ip, NC_UBYTE);
1061 }
1062 
1063 int
nc_get_var_short(int ncid,int varid,short * ip)1064 nc_get_var_short(int ncid, int varid, short *ip)
1065 {
1066    NC* ncp;
1067    int stat = NC_check_id(ncid, &ncp);
1068    if(stat != NC_NOERR) return stat;
1069    return NC_get_var(ncid, varid, (void *)ip, NC_SHORT);
1070 }
1071 
1072 int
nc_get_var_int(int ncid,int varid,int * ip)1073 nc_get_var_int(int ncid, int varid, int *ip)
1074 {
1075    NC* ncp;
1076    int stat = NC_check_id(ncid, &ncp);
1077    if(stat != NC_NOERR) return stat;
1078    return NC_get_var(ncid,varid, (void *)ip, NC_INT);
1079 }
1080 
1081 int
nc_get_var_long(int ncid,int varid,long * ip)1082 nc_get_var_long(int ncid, int varid, long *ip)
1083 {
1084    NC* ncp;
1085    int stat = NC_check_id(ncid, &ncp);
1086    if(stat != NC_NOERR) return stat;
1087    return NC_get_var(ncid,varid, (void *)ip, longtype);
1088 }
1089 
1090 int
nc_get_var_float(int ncid,int varid,float * ip)1091 nc_get_var_float(int ncid, int varid, float *ip)
1092 {
1093    NC* ncp;
1094    int stat = NC_check_id(ncid, &ncp);
1095    if(stat != NC_NOERR) return stat;
1096    return NC_get_var(ncid,varid, (void *)ip, NC_FLOAT);
1097 }
1098 
1099 int
nc_get_var_double(int ncid,int varid,double * ip)1100 nc_get_var_double(int ncid, int varid, double *ip)
1101 {
1102    NC* ncp;
1103    int stat = NC_check_id(ncid, &ncp);
1104    if(stat != NC_NOERR) return stat;
1105    return NC_get_var(ncid,varid, (void *)ip, NC_DOUBLE);
1106 }
1107 
1108 int
nc_get_var_ubyte(int ncid,int varid,unsigned char * ip)1109 nc_get_var_ubyte(int ncid, int varid, unsigned char *ip)
1110 {
1111    NC* ncp;
1112    int stat = NC_check_id(ncid, &ncp);
1113    if(stat != NC_NOERR) return stat;
1114    return NC_get_var(ncid,varid, (void *)ip, NC_UBYTE);
1115 }
1116 
1117 int
nc_get_var_ushort(int ncid,int varid,unsigned short * ip)1118 nc_get_var_ushort(int ncid, int varid, unsigned short *ip)
1119 {
1120    NC* ncp;
1121    int stat = NC_check_id(ncid, &ncp);
1122    if(stat != NC_NOERR) return stat;
1123    return NC_get_var(ncid,varid, (void *)ip, NC_USHORT);
1124 }
1125 
1126 int
nc_get_var_uint(int ncid,int varid,unsigned int * ip)1127 nc_get_var_uint(int ncid, int varid, unsigned int *ip)
1128 {
1129    NC* ncp;
1130    int stat = NC_check_id(ncid, &ncp);
1131    if(stat != NC_NOERR) return stat;
1132    return NC_get_var(ncid,varid, (void *)ip, NC_UINT);
1133 }
1134 
1135 int
nc_get_var_longlong(int ncid,int varid,long long * ip)1136 nc_get_var_longlong(int ncid, int varid, long long *ip)
1137 {
1138    NC* ncp;
1139    int stat = NC_check_id(ncid, &ncp);
1140    if(stat != NC_NOERR) return stat;
1141    return NC_get_var(ncid,varid, (void *)ip, NC_INT64);
1142 }
1143 
1144 int
nc_get_var_ulonglong(int ncid,int varid,unsigned long long * ip)1145 nc_get_var_ulonglong(int ncid, int varid, unsigned long long *ip)
1146 {
1147    NC* ncp;
1148    int stat = NC_check_id(ncid, &ncp);
1149    if(stat != NC_NOERR) return stat;
1150    return NC_get_var(ncid,varid, (void *)ip,NC_UINT64);
1151 }
1152 
1153 #ifdef USE_NETCDF4
1154 int
nc_get_var_string(int ncid,int varid,char ** ip)1155 nc_get_var_string(int ncid, int varid, char* *ip)
1156 {
1157    NC* ncp;
1158    int stat = NC_check_id(ncid, &ncp);
1159    if(stat != NC_NOERR) return stat;
1160    return NC_get_var(ncid,varid, (void *)ip,NC_STRING);
1161 }
1162 #endif /*USE_NETCDF4*/
1163 /** \} */
1164 
1165 /** \ingroup variables
1166 Read a strided array from a variable.
1167 
1168 This function reads a subsampled (strided) array section of values
1169 from a netCDF variable of an open netCDF dataset. The subsampled array
1170 section is specified by giving a corner, a vector of edge lengths, and
1171 a stride vector. The values are read with the last dimension of the
1172 netCDF variable varying fastest. The netCDF dataset must be in data
1173 mode.
1174 
1175 The nc_get_vars() function will read a variable of any type, including
1176 user defined type. For this function, the type of the data in memory
1177 must match the type of the variable - no data conversion is done.
1178 
1179 \param ncid NetCDF or group ID, from a previous call to nc_open(),
1180 nc_create(), nc_def_grp(), or associated inquiry functions such as
1181 nc_inq_ncid().
1182 
1183 \param varid Variable ID
1184 
1185 \param startp Start vector with one element for each dimension to \ref
1186 specify_hyperslab.
1187 
1188 \param countp Count vector with one element for each dimension to \ref
1189 specify_hyperslab.
1190 
1191 \param stridep Stride vector with one element for each dimension to
1192 \ref specify_hyperslab.
1193 
1194 \param ip Pointer where the data will be copied. Memory must be
1195 allocated by the user before this function is called.
1196 
1197 \returns ::NC_NOERR No error.
1198 \returns ::NC_ENOTVAR Variable not found.
1199 \returns ::NC_EINVALCOORDS Index exceeds dimension bound.
1200 \returns ::NC_ERANGE One or more of the values are out of range.
1201 \returns ::NC_EINDEFINE Operation not allowed in define mode.
1202 \returns ::NC_EBADID Bad ncid.
1203 */
1204 /** \{ */
1205 int
nc_get_vars(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,void * ip)1206 nc_get_vars (int ncid, int varid, const size_t * startp,
1207 	     const size_t * countp, const ptrdiff_t * stridep,
1208 	     void *ip)
1209 {
1210    NC* ncp;
1211    int stat = NC_NOERR;
1212 
1213    if ((stat = NC_check_id(ncid, &ncp)))
1214        return stat;
1215    return ncp->dispatch->get_vars(ncid, varid, startp, countp, stridep,
1216 		      ip, NC_NAT);
1217 }
1218 
1219 int
nc_get_vars_text(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,char * ip)1220 nc_get_vars_text(int ncid, int varid, const size_t *startp,
1221 		 const size_t *countp, const ptrdiff_t * stridep,
1222 		 char *ip)
1223 {
1224    NC* ncp;
1225    int stat = NC_check_id(ncid, &ncp);
1226    if(stat != NC_NOERR) return stat;
1227    return NC_get_vars(ncid,varid,startp, countp, stridep,
1228 		      (void *)ip, NC_CHAR);
1229 }
1230 
1231 int
nc_get_vars_schar(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,signed char * ip)1232 nc_get_vars_schar(int ncid, int varid, const size_t *startp,
1233 		  const size_t *countp, const ptrdiff_t * stridep,
1234 		  signed char *ip)
1235 {
1236    NC* ncp;
1237    int stat = NC_check_id(ncid, &ncp);
1238    if(stat != NC_NOERR) return stat;
1239    return NC_get_vars(ncid,varid,startp, countp, stridep,
1240 		      (void *)ip, NC_BYTE);
1241 }
1242 
1243 int
nc_get_vars_uchar(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,unsigned char * ip)1244 nc_get_vars_uchar(int ncid, int varid, const size_t *startp,
1245 		  const size_t *countp, const ptrdiff_t * stridep,
1246 		  unsigned char *ip)
1247 {
1248    NC* ncp;
1249    int stat = NC_check_id(ncid, &ncp);
1250    if(stat != NC_NOERR) return stat;
1251    return NC_get_vars(ncid,varid,startp, countp, stridep,
1252 		      (void *)ip, T_uchar);
1253 }
1254 
1255 int
nc_get_vars_short(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,short * ip)1256 nc_get_vars_short(int ncid, int varid, const size_t *startp,
1257 		  const size_t *countp, const ptrdiff_t *stridep,
1258 		  short *ip)
1259 {
1260    NC* ncp;
1261    int stat = NC_check_id(ncid, &ncp);
1262    if(stat != NC_NOERR) return stat;
1263    return NC_get_vars(ncid,varid,startp, countp, stridep,
1264 		      (void *)ip, NC_SHORT);
1265 }
1266 
1267 int
nc_get_vars_int(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,int * ip)1268 nc_get_vars_int(int ncid, int varid, const size_t *startp,
1269 		const size_t *countp, const ptrdiff_t * stridep,
1270 		int *ip)
1271 {
1272    NC* ncp;
1273    int stat = NC_check_id(ncid, &ncp);
1274    if(stat != NC_NOERR) return stat;
1275    return NC_get_vars(ncid,varid,startp, countp, stridep,
1276 		      (void *)ip, NC_INT);
1277 }
1278 
1279 int
nc_get_vars_long(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,long * ip)1280 nc_get_vars_long(int ncid, int varid, const size_t *startp,
1281 		 const size_t *countp, const ptrdiff_t * stridep,
1282 		 long *ip)
1283 {
1284    NC* ncp;
1285    int stat = NC_check_id(ncid, &ncp);
1286    if(stat != NC_NOERR) return stat;
1287    return NC_get_vars(ncid,varid,startp, countp, stridep,
1288 		      (void *)ip, T_long);
1289 }
1290 
1291 int
nc_get_vars_float(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,float * ip)1292 nc_get_vars_float(int ncid, int varid, const size_t *startp,
1293 		  const size_t *countp, const ptrdiff_t * stridep,
1294 		  float *ip)
1295 {
1296    NC* ncp;
1297    int stat = NC_check_id(ncid, &ncp);
1298    if(stat != NC_NOERR) return stat;
1299    return NC_get_vars(ncid,varid,startp, countp, stridep,
1300 		      (void *)ip, T_float);
1301 }
1302 
1303 int
nc_get_vars_double(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,double * ip)1304 nc_get_vars_double(int ncid, int varid, const size_t *startp,
1305 		   const size_t *countp, const ptrdiff_t * stridep,
1306 		   double *ip)
1307 {
1308    NC* ncp;
1309    int stat = NC_check_id(ncid, &ncp);
1310    if(stat != NC_NOERR) return stat;
1311    return NC_get_vars(ncid,varid,startp, countp, stridep,
1312 		      (void *)ip, T_double);
1313 }
1314 
1315 int
nc_get_vars_ubyte(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,unsigned char * ip)1316 nc_get_vars_ubyte(int ncid, int varid, const size_t *startp,
1317 		  const size_t *countp, const ptrdiff_t * stridep,
1318 		  unsigned char *ip)
1319 {
1320    NC* ncp;
1321    int stat = NC_check_id(ncid, &ncp);
1322    if(stat != NC_NOERR) return stat;
1323    return NC_get_vars(ncid,varid, startp, countp, stridep,
1324 		      (void *)ip, T_ubyte);
1325 }
1326 
1327 int
nc_get_vars_ushort(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,unsigned short * ip)1328 nc_get_vars_ushort(int ncid, int varid, const size_t *startp,
1329 		   const size_t *countp, const ptrdiff_t * stridep,
1330 		   unsigned short *ip)
1331 {
1332    NC* ncp;
1333    int stat = NC_check_id(ncid, &ncp);
1334    if(stat != NC_NOERR) return stat;
1335    return NC_get_vars(ncid,varid,startp,countp, stridep,
1336 		      (void *)ip, T_ushort);
1337 }
1338 
1339 int
nc_get_vars_uint(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,unsigned int * ip)1340 nc_get_vars_uint(int ncid, int varid, const size_t *startp,
1341 		 const size_t *countp, const ptrdiff_t * stridep,
1342 		 unsigned int *ip)
1343 {
1344    NC* ncp;
1345    int stat = NC_check_id(ncid, &ncp);
1346    if(stat != NC_NOERR) return stat;
1347    return NC_get_vars(ncid,varid,startp, countp, stridep,
1348 		      (void *)ip, T_uint);
1349 }
1350 
1351 int
nc_get_vars_longlong(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,long long * ip)1352 nc_get_vars_longlong(int ncid, int varid, const size_t *startp,
1353 		     const size_t *countp, const ptrdiff_t * stridep,
1354 		     long long *ip)
1355 {
1356    NC* ncp;
1357    int stat = NC_check_id(ncid, &ncp);
1358    if(stat != NC_NOERR) return stat;
1359    return NC_get_vars(ncid, varid, startp, countp, stridep,
1360 		      (void *)ip, T_longlong);
1361 }
1362 
1363 int
nc_get_vars_ulonglong(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,unsigned long long * ip)1364 nc_get_vars_ulonglong(int ncid, int varid, const size_t *startp,
1365 		      const size_t *countp, const ptrdiff_t * stridep,
1366 		      unsigned long long *ip)
1367 {
1368    NC* ncp;
1369    int stat = NC_check_id(ncid, &ncp);
1370    if(stat != NC_NOERR) return stat;
1371    return NC_get_vars(ncid, varid, startp, countp, stridep,
1372 		      (void *)ip, NC_UINT64);
1373 }
1374 
1375 #ifdef USE_NETCDF4
1376 int
nc_get_vars_string(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,char ** ip)1377 nc_get_vars_string(int ncid, int varid,
1378 		   const size_t *startp, const size_t *countp,
1379 		   const ptrdiff_t * stridep,
1380 		   char* *ip)
1381 {
1382    NC* ncp;
1383    int stat = NC_check_id(ncid, &ncp);
1384    if(stat != NC_NOERR) return stat;
1385    return NC_get_vars(ncid, varid, startp, countp, stridep,
1386 		      (void *)ip, NC_STRING);
1387 }
1388 #endif /*USE_NETCDF4*/
1389 /** \} */
1390 
1391 /** \ingroup variables
1392 Read a mapped array from a variable.
1393 
1394 The nc_get_varm_ type family of functions reads a mapped array section
1395 of values from a netCDF variable of an open netCDF dataset. The mapped
1396 array section is specified by giving a corner, a vector of edge
1397 lengths, a stride vector, and an index mapping vector. The index
1398 mapping vector is a vector of integers that specifies the mapping
1399 between the dimensions of a netCDF variable and the in-memory
1400 structure of the internal data array. No assumptions are made about
1401 the ordering or length of the dimensions of the data array. The netCDF
1402 dataset must be in data mode.
1403 
1404 The functions for types ubyte, ushort, uint, longlong, ulonglong, and
1405 string are only available for netCDF-4/HDF5 files.
1406 
1407 The nc_get_varm() function will only read a variable of an
1408 atomic type; it will not read user defined types. For this
1409 function, the type of the data in memory must match the type
1410 of the variable - no data conversion is done.
1411 
1412 @deprecated Use of this family of functions is discouraged,
1413 although it will continue to be supported.
1414 The reason is the complexity of the
1415 algorithm makes its use difficult for users to properly use.
1416 
1417 \param ncid NetCDF or group ID, from a previous call to nc_open(),
1418 nc_create(), nc_def_grp(), or associated inquiry functions such as
1419 nc_inq_ncid().
1420 
1421 \param varid Variable ID
1422 
1423 \param startp Start vector with one element for each dimension to \ref
1424 specify_hyperslab.
1425 
1426 \param countp Count vector with one element for each dimension to \ref
1427 specify_hyperslab.
1428 
1429 \param stridep Stride vector with one element for each dimension to
1430 \ref specify_hyperslab.
1431 
1432 \param imapp Mapping vector with one element for each dimension to
1433 \ref specify_hyperslab.
1434 
1435 \param ip Pointer where the data will be copied. Memory must be
1436 allocated by the user before this function is called.
1437 
1438 \returns ::NC_NOERR No error.
1439 \returns ::NC_ENOTVAR Variable not found.
1440 \returns ::NC_EINVALCOORDS Index exceeds dimension bound.
1441 \returns ::NC_ERANGE One or more of the values are out of range.
1442 \returns ::NC_EINDEFINE Operation not allowed in define mode.
1443 \returns ::NC_EBADID Bad ncid.
1444 */
1445 /** \{ */
1446 int
nc_get_varm(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,void * ip)1447 nc_get_varm(int ncid, int varid, const size_t * startp,
1448 	    const size_t * countp, const ptrdiff_t * stridep,
1449 	    const ptrdiff_t * imapp, void *ip)
1450 {
1451    NC* ncp;
1452    int stat = NC_NOERR;
1453 
1454    if ((stat = NC_check_id(ncid, &ncp)))
1455        return stat;
1456    return ncp->dispatch->get_varm(ncid, varid, startp, countp,
1457 				  stridep, imapp, ip, NC_NAT);
1458 }
1459 
1460 int
nc_get_varm_schar(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,signed char * ip)1461 nc_get_varm_schar(int ncid, int varid,
1462 		  const size_t *startp, const size_t *countp,
1463 		  const ptrdiff_t *stridep,
1464 		  const ptrdiff_t *imapp, signed char *ip)
1465 {
1466    NC *ncp;
1467    int stat = NC_check_id(ncid, &ncp);
1468    if(stat != NC_NOERR) return stat;
1469    return NC_get_varm(ncid, varid, startp, countp,
1470 		      stridep, imapp, (void *)ip, NC_BYTE);
1471 }
1472 
1473 int
nc_get_varm_uchar(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,unsigned char * ip)1474 nc_get_varm_uchar(int ncid, int varid,
1475 		  const size_t *startp, const size_t *countp,
1476 		  const ptrdiff_t *stridep, const ptrdiff_t *imapp,
1477 		  unsigned char *ip)
1478 {
1479    NC *ncp;
1480    int stat = NC_check_id(ncid, &ncp);
1481    if(stat != NC_NOERR) return stat;
1482    return NC_get_varm(ncid,varid,startp,countp,stridep,imapp, (void *)ip,T_uchar);
1483 }
1484 
1485 int
nc_get_varm_short(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,short * ip)1486 nc_get_varm_short(int ncid, int varid, const size_t *startp,
1487 		  const size_t *countp, const ptrdiff_t *stridep,
1488 		  const ptrdiff_t *imapp, short *ip)
1489 {
1490    NC *ncp;
1491    int stat = NC_check_id(ncid, &ncp);
1492    if(stat != NC_NOERR) return stat;
1493    return NC_get_varm(ncid,varid,startp,countp,stridep,imapp, (void *)ip,NC_SHORT);
1494 }
1495 
1496 int
nc_get_varm_int(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,int * ip)1497 nc_get_varm_int(int ncid, int varid,
1498 		const size_t *startp, const size_t *countp,
1499 		const ptrdiff_t *stridep, const ptrdiff_t *imapp,
1500 		int *ip)
1501 {
1502    NC *ncp;
1503    int stat = NC_check_id(ncid, &ncp);
1504    if(stat != NC_NOERR) return stat;
1505    return NC_get_varm(ncid,varid,startp,countp,stridep,imapp, (void *)ip,NC_INT);
1506 }
1507 
1508 int
nc_get_varm_long(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,long * ip)1509 nc_get_varm_long(int ncid, int varid,
1510 		 const size_t *startp, const size_t *countp,
1511 		 const ptrdiff_t *stridep, const ptrdiff_t *imapp,
1512 		 long *ip)
1513 {
1514    NC *ncp;
1515    int stat = NC_check_id(ncid, &ncp);
1516    if(stat != NC_NOERR) return stat;
1517    return NC_get_varm(ncid,varid,startp,countp,stridep,imapp, (void *)ip,T_long);
1518 }
1519 
1520 int
nc_get_varm_float(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,float * ip)1521 nc_get_varm_float(int ncid, int varid,
1522 		  const size_t *startp, const size_t *countp,
1523 		  const ptrdiff_t *stridep, const ptrdiff_t *imapp,
1524 		  float *ip)
1525 {
1526    NC *ncp;
1527    int stat = NC_check_id(ncid, &ncp);
1528    if(stat != NC_NOERR) return stat;
1529    return NC_get_varm(ncid,varid,startp,countp,stridep,imapp, (void *)ip,T_float);
1530 }
1531 
1532 int
nc_get_varm_double(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,double * ip)1533 nc_get_varm_double(int ncid, int varid,
1534 		   const size_t *startp, const size_t *countp,
1535 		   const ptrdiff_t *stridep, const ptrdiff_t *imapp,
1536 		   double *ip)
1537 {
1538    NC *ncp;
1539    int stat = NC_check_id(ncid, &ncp);
1540    if(stat != NC_NOERR) return stat;
1541    return NC_get_varm(ncid,varid,startp,countp,stridep,imapp, (void *)ip,T_double);
1542 }
1543 
1544 int
nc_get_varm_ubyte(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,unsigned char * ip)1545 nc_get_varm_ubyte(int ncid, int varid,
1546 		  const size_t *startp, const size_t *countp,
1547 		  const ptrdiff_t *stridep, const ptrdiff_t *imapp,
1548 		  unsigned char *ip)
1549 {
1550    NC *ncp;
1551    int stat = NC_check_id(ncid, &ncp);
1552    if(stat != NC_NOERR) return stat;
1553    return NC_get_varm(ncid,varid,startp,countp,stridep,
1554 		      imapp, (void *)ip, T_ubyte);
1555 }
1556 
1557 int
nc_get_varm_ushort(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,unsigned short * ip)1558 nc_get_varm_ushort(int ncid, int varid,
1559 		   const size_t *startp, const size_t *countp,
1560 		   const ptrdiff_t *stridep, const ptrdiff_t *imapp,
1561 		   unsigned short *ip)
1562 {
1563    NC *ncp;
1564    int stat = NC_check_id(ncid, &ncp);
1565    if(stat != NC_NOERR) return stat;
1566    return NC_get_varm(ncid, varid, startp, countp, stridep,
1567 		      imapp, (void *)ip, T_ushort);
1568 }
1569 
1570 int
nc_get_varm_uint(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,unsigned int * ip)1571 nc_get_varm_uint(int ncid, int varid,
1572 		 const size_t *startp, const size_t *countp,
1573 		 const ptrdiff_t *stridep, const ptrdiff_t *imapp,
1574 		 unsigned int *ip)
1575 {
1576    NC *ncp;
1577    int stat = NC_check_id(ncid, &ncp);
1578    if(stat != NC_NOERR) return stat;
1579    return NC_get_varm(ncid, varid, startp, countp,
1580 		      stridep, imapp, (void *)ip, T_uint);
1581 }
1582 
1583 int
nc_get_varm_longlong(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,long long * ip)1584 nc_get_varm_longlong(int ncid, int varid, const size_t *startp,
1585 		     const size_t *countp, const ptrdiff_t *stridep,
1586 		     const ptrdiff_t *imapp, long long *ip)
1587 {
1588    NC *ncp;
1589    int stat = NC_check_id(ncid, &ncp);
1590    if(stat != NC_NOERR) return stat;
1591    return NC_get_varm(ncid, varid, startp, countp, stridep, imapp,
1592 		      (void *)ip, T_longlong);
1593 }
1594 
1595 int
nc_get_varm_ulonglong(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,unsigned long long * ip)1596 nc_get_varm_ulonglong(int ncid, int varid,
1597 		      const size_t *startp, const size_t *countp,
1598 		      const ptrdiff_t *stridep, const ptrdiff_t *imapp,
1599 		      unsigned long long *ip)
1600 {
1601    NC *ncp;
1602    int stat = NC_check_id(ncid, &ncp);
1603    if(stat != NC_NOERR) return stat;
1604    return NC_get_varm(ncid, varid, startp, countp, stridep, imapp,
1605 		      (void *)ip, NC_UINT64);
1606 }
1607 
1608 int
nc_get_varm_text(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,char * ip)1609 nc_get_varm_text(int ncid, int varid, const size_t *startp,
1610 		 const size_t *countp, const ptrdiff_t *stridep,
1611 		 const ptrdiff_t *imapp, char *ip)
1612 {
1613    NC *ncp;
1614    int stat = NC_check_id(ncid, &ncp);
1615    if(stat != NC_NOERR) return stat;
1616    return NC_get_varm(ncid, varid, startp, countp, stridep, imapp,
1617 		      (void *)ip, NC_CHAR);
1618 }
1619 
1620 #ifdef USE_NETCDF4
1621 int
nc_get_varm_string(int ncid,int varid,const size_t * startp,const size_t * countp,const ptrdiff_t * stridep,const ptrdiff_t * imapp,char ** ip)1622 nc_get_varm_string(int ncid, int varid, const size_t *startp,
1623 		   const size_t *countp, const ptrdiff_t *stridep,
1624 		   const ptrdiff_t *imapp, char **ip)
1625 {
1626    NC *ncp;
1627    int stat = NC_check_id(ncid, &ncp);
1628    if(stat != NC_NOERR) return stat;
1629    return NC_get_varm(ncid, varid, startp, countp, stridep, imapp,
1630 		      (void *)ip, NC_STRING);
1631 }
1632 /** \} */
1633 #endif /*USE_NETCDF4*/
1634 
1635 
1636 /*! \} */ /* End of named group... */
1637