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