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