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