PageRenderTime 51ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/other/netcdf_write_matrix/src/libsrc/putget.m4

http://github.com/jbeezley/wrf-fire
m4 | 2524 lines | 2128 code | 321 blank | 75 comment | 0 complexity | 0e16c6ea3a245443ec028d1f05220d3f MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. dnl This is m4 source.
  2. dnl Process using m4 to produce 'C' language file.
  3. dnl
  4. undefine(`begin')dnl
  5. undefine(`index')dnl
  6. undefine(`len')dnl
  7. dnl
  8. dnl If you see this line, you can ignore the next one.
  9. /* Do not edit this file. It is produced from the corresponding .m4 source */
  10. dnl
  11. /*
  12. * Copyright 1996, University Corporation for Atmospheric Research
  13. * See netcdf/COPYRIGHT file for copying and redistribution conditions.
  14. */
  15. /* $Id: putget.m4,v 2.60 2006/01/03 20:20:07 russ Exp $ */
  16. #include "nc.h"
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <assert.h>
  20. #include "ncx.h"
  21. #include "fbits.h"
  22. #include "onstack.h"
  23. #ifdef LOCKNUMREC
  24. # include <mpp/shmem.h> /* for SGI/Cray SHMEM routines */
  25. # ifdef LN_TEST
  26. # include <stdio.h>
  27. # endif
  28. #endif
  29. #undef MIN /* system may define MIN somewhere and complain */
  30. #define MIN(mm,nn) (((mm) < (nn)) ? (mm) : (nn))
  31. /* #define ODEBUG 1 */
  32. #if ODEBUG
  33. #include <stdio.h>
  34. /*
  35. * Print the values of an array of size_t
  36. */
  37. void
  38. arrayp(const char *label, size_t count, const size_t *array)
  39. {
  40. (void) fprintf(stderr, "%s", label);
  41. (void) fputc('\t',stderr);
  42. for(; count > 0; count--, array++)
  43. (void) fprintf(stderr," %lu", (unsigned long)*array);
  44. (void) fputc('\n',stderr);
  45. }
  46. #endif /* ODEBUG */
  47. /*
  48. * This is how much space is required by the user, as in
  49. *
  50. * vals = malloc(nel * nctypelen(var.type));
  51. * ncvarget(cdfid, varid, cor, edg, vals);
  52. */
  53. int
  54. nctypelen(nc_type type)
  55. {
  56. switch(type){
  57. case NC_BYTE :
  58. case NC_CHAR :
  59. return((int)sizeof(char));
  60. case NC_SHORT :
  61. return(int)(sizeof(short));
  62. case NC_INT :
  63. return((int)sizeof(int));
  64. case NC_FLOAT :
  65. return((int)sizeof(float));
  66. case NC_DOUBLE :
  67. return((int)sizeof(double));
  68. }
  69. return -1;
  70. }
  71. /* Begin fill */
  72. /*
  73. * This is tunable parameter.
  74. * It essentially controls the tradeoff between the number of times
  75. * memcpy() gets called to copy the external data to fill
  76. * a large buffer vs the number of times its called to
  77. * prepare the external data.
  78. */
  79. #if _SX
  80. /* NEC SX specific optimization */
  81. #define NFILL 2048
  82. #else
  83. #define NFILL 16
  84. #endif
  85. dnl
  86. dnl NCFILL(Type, Xtype, XSize, Fill)
  87. dnl
  88. define(`NCFILL',dnl
  89. `dnl
  90. static int
  91. NC_fill_$2(
  92. void **xpp,
  93. size_t nelems) /* how many */
  94. {
  95. $1 fillp[NFILL * sizeof(double)/$3];
  96. assert(nelems <= sizeof(fillp)/sizeof(fillp[0]));
  97. {
  98. $1 *vp = fillp; /* lower bound of area to be filled */
  99. const $1 *const end = vp + nelems;
  100. while(vp < end)
  101. {
  102. *vp++ = $4;
  103. }
  104. }
  105. return ncx_putn_$2_$1(xpp, nelems, fillp);
  106. }
  107. ')dnl
  108. /*
  109. * Next 6 type specific functions
  110. * Fill a some memory with the default special value.
  111. * Formerly
  112. NC_arrayfill()
  113. */
  114. NCFILL(schar, schar, X_SIZEOF_CHAR, NC_FILL_BYTE)
  115. NCFILL(char, char, X_SIZEOF_CHAR, NC_FILL_CHAR)
  116. NCFILL(short, short, X_SIZEOF_SHORT, NC_FILL_SHORT)
  117. #if (SIZEOF_INT >= X_SIZEOF_INT)
  118. NCFILL(int, int, X_SIZEOF_INT, NC_FILL_INT)
  119. #elif SIZEOF_LONG == X_SIZEOF_INT
  120. NCFILL(long, int, X_SIZEOF_INT, NC_FILL_INT)
  121. #else
  122. #error "NC_fill_int implementation"
  123. #endif
  124. NCFILL(float, float, X_SIZEOF_FLOAT, NC_FILL_FLOAT)
  125. NCFILL(double, double, X_SIZEOF_DOUBLE, NC_FILL_DOUBLE)
  126. /*
  127. * Fill the external space for variable 'varp' values at 'recno'
  128. * with the appropriate value. If 'varp' is not a record
  129. * variable, fill the whole thing.
  130. * Formerly
  131. xdr_NC_fill()
  132. */
  133. int
  134. fill_NC_var(NC *ncp, const NC_var *varp, size_t recno)
  135. {
  136. char xfillp[NFILL * X_SIZEOF_DOUBLE];
  137. const size_t step = varp->xsz;
  138. const size_t nelems = sizeof(xfillp)/step;
  139. const size_t xsz = varp->xsz * nelems;
  140. NC_attr **attrpp = NULL;
  141. off_t offset;
  142. size_t remaining = varp->len;
  143. void *xp;
  144. int status = NC_NOERR;
  145. /*
  146. * Set up fill value
  147. */
  148. attrpp = NC_findattr(&varp->attrs, _FillValue);
  149. if( attrpp != NULL )
  150. {
  151. /* User defined fill value */
  152. if( (*attrpp)->type != varp->type || (*attrpp)->nelems != 1 )
  153. {
  154. return NC_EBADTYPE;
  155. }
  156. else
  157. {
  158. /* Use the user defined value */
  159. char *cp = xfillp;
  160. const char *const end = &xfillp[sizeof(xfillp)];
  161. assert(step <= (*attrpp)->xsz);
  162. for( /*NADA*/; cp < end; cp += step)
  163. {
  164. (void) memcpy(cp, (*attrpp)->xvalue, step);
  165. }
  166. }
  167. }
  168. else
  169. {
  170. /* use the default */
  171. assert(xsz % X_ALIGN == 0);
  172. assert(xsz <= sizeof(xfillp));
  173. xp = xfillp;
  174. switch(varp->type){
  175. case NC_BYTE :
  176. status = NC_fill_schar(&xp, nelems);
  177. break;
  178. case NC_CHAR :
  179. status = NC_fill_char(&xp, nelems);
  180. break;
  181. case NC_SHORT :
  182. status = NC_fill_short(&xp, nelems);
  183. break;
  184. case NC_INT :
  185. status = NC_fill_int(&xp, nelems);
  186. break;
  187. case NC_FLOAT :
  188. status = NC_fill_float(&xp, nelems);
  189. break;
  190. case NC_DOUBLE :
  191. status = NC_fill_double(&xp, nelems);
  192. break;
  193. default :
  194. assert("fill_NC_var invalid type" == 0);
  195. status = NC_EBADTYPE;
  196. break;
  197. }
  198. if(status != NC_NOERR)
  199. return status;
  200. assert(xp == xfillp + xsz);
  201. }
  202. /*
  203. * copyout:
  204. * xfillp now contains 'nelems' elements of the fill value
  205. * in external representation.
  206. */
  207. /*
  208. * Copy it out.
  209. */
  210. offset = varp->begin;
  211. if(IS_RECVAR(varp))
  212. {
  213. offset += (off_t)ncp->recsize * recno;
  214. }
  215. assert(remaining > 0);
  216. for(;;)
  217. {
  218. const size_t chunksz = MIN(remaining, ncp->chunk);
  219. size_t ii;
  220. assert(chunksz % X_ALIGN == 0);
  221. status = ncp->nciop->get(ncp->nciop, offset, chunksz,
  222. RGN_WRITE, &xp);
  223. if(status != NC_NOERR)
  224. {
  225. return status;
  226. }
  227. /*
  228. * fill the chunksz buffer in units of xsz
  229. */
  230. for(ii = 0; ii < chunksz/xsz; ii++)
  231. {
  232. (void) memcpy(xp, xfillp, xsz);
  233. xp = (char *)xp + xsz;
  234. }
  235. /*
  236. * Deal with any remainder
  237. */
  238. {
  239. const size_t rem = chunksz % xsz;
  240. if(rem != 0)
  241. {
  242. (void) memcpy(xp, xfillp, rem);
  243. /* xp = (char *)xp + xsz; */
  244. }
  245. }
  246. status = ncp->nciop->rel(ncp->nciop, offset, RGN_MODIFIED);
  247. if(status != NC_NOERR)
  248. {
  249. break;
  250. }
  251. remaining -= chunksz;
  252. if(remaining == 0)
  253. break; /* normal loop exit */
  254. offset += chunksz;
  255. }
  256. return status;
  257. }
  258. /* End fill */
  259. /*
  260. * Add a record containing the fill values.
  261. */
  262. static int
  263. NCfillrecord(NC *ncp, const NC_var *const *varpp, size_t recno)
  264. {
  265. size_t ii = 0;
  266. for(; ii < ncp->vars.nelems; ii++, varpp++)
  267. {
  268. if( !IS_RECVAR(*varpp) )
  269. {
  270. continue; /* skip non-record variables */
  271. }
  272. {
  273. const int status = fill_NC_var(ncp, *varpp, recno);
  274. if(status != NC_NOERR)
  275. return status;
  276. }
  277. }
  278. return NC_NOERR;
  279. }
  280. /*
  281. * It is advantageous to
  282. * #define TOUCH_LAST
  283. * when using memory mapped io.
  284. */
  285. #if TOUCH_LAST
  286. /*
  287. * Grow the file to a size which can contain recno
  288. */
  289. static int
  290. NCtouchlast(NC *ncp, const NC_var *const *varpp, size_t recno)
  291. {
  292. int status = NC_NOERR;
  293. const NC_var *varp = NULL;
  294. {
  295. size_t ii = 0;
  296. for(; ii < ncp->vars.nelems; ii++, varpp++)
  297. {
  298. if( !IS_RECVAR(*varpp) )
  299. {
  300. continue; /* skip non-record variables */
  301. }
  302. varp = *varpp;
  303. }
  304. }
  305. assert(varp != NULL);
  306. assert( IS_RECVAR(varp) );
  307. {
  308. const off_t offset = varp->begin
  309. + (off_t)(recno-1) * (off_t)ncp->recsize
  310. + (off_t)(varp->len - varp->xsz);
  311. void *xp;
  312. status = ncp->nciop->get(ncp->nciop, offset, varp->xsz,
  313. RGN_WRITE, &xp);
  314. if(status != NC_NOERR)
  315. return status;
  316. (void)memset(xp, 0, varp->xsz);
  317. status = ncp->nciop->rel(ncp->nciop, offset, RGN_MODIFIED);
  318. }
  319. return status;
  320. }
  321. #endif /* TOUCH_LAST */
  322. /*
  323. * Ensure that the netcdf file has 'numrecs' records,
  324. * add records and fill as neccessary.
  325. */
  326. static int
  327. NCvnrecs(NC *ncp, size_t numrecs)
  328. {
  329. int status = NC_NOERR;
  330. #ifdef LOCKNUMREC
  331. ushmem_t myticket = 0, nowserving = 0;
  332. ushmem_t numpe = (ushmem_t) _num_pes();
  333. /* get ticket and wait */
  334. myticket = shmem_short_finc((shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
  335. ncp->lock[LOCKNUMREC_BASEPE]);
  336. #ifdef LN_TEST
  337. fprintf(stderr,"%d of %d : ticket = %hu\n",
  338. _my_pe(), _num_pes(), myticket);
  339. #endif
  340. do {
  341. shmem_short_get((shmem_t *) &nowserving,
  342. (shmem_t *) ncp->lock + LOCKNUMREC_SERVING, 1,
  343. ncp->lock[LOCKNUMREC_BASEPE]);
  344. #ifdef LN_TEST
  345. fprintf(stderr,"%d of %d : serving = %hu\n",
  346. _my_pe(), _num_pes(), nowserving);
  347. #endif
  348. /* work-around for non-unique tickets */
  349. if (nowserving > myticket && nowserving < myticket + numpe ) {
  350. /* get a new ticket ... you've been bypassed */
  351. /* and handle the unlikely wrap-around effect */
  352. myticket = shmem_short_finc(
  353. (shmem_t *) ncp->lock + LOCKNUMREC_LOCK,
  354. ncp->lock[LOCKNUMREC_BASEPE]);
  355. #ifdef LN_TEST
  356. fprintf(stderr,"%d of %d : new ticket = %hu\n",
  357. _my_pe(), _num_pes(), myticket);
  358. #endif
  359. }
  360. } while(nowserving != myticket);
  361. /* now our turn to check & update value */
  362. #endif
  363. if(numrecs > NC_get_numrecs(ncp))
  364. {
  365. #if TOUCH_LAST
  366. status = NCtouchlast(ncp,
  367. (const NC_var *const*)ncp->vars.value,
  368. numrecs);
  369. if(status != NC_NOERR)
  370. goto common_return;
  371. #endif /* TOUCH_LAST */
  372. set_NC_ndirty(ncp);
  373. if(!NC_dofill(ncp))
  374. {
  375. /* Simply set the new numrecs value */
  376. NC_set_numrecs(ncp, numrecs);
  377. }
  378. else
  379. {
  380. /* Fill each record out to numrecs */
  381. size_t cur_nrecs;
  382. while((cur_nrecs = NC_get_numrecs(ncp)) < numrecs)
  383. {
  384. status = NCfillrecord(ncp,
  385. (const NC_var *const*)ncp->vars.value,
  386. cur_nrecs);
  387. if(status != NC_NOERR)
  388. {
  389. break;
  390. }
  391. NC_increase_numrecs(ncp, cur_nrecs +1);
  392. }
  393. if(status != NC_NOERR)
  394. goto common_return;
  395. }
  396. if(NC_doNsync(ncp))
  397. {
  398. status = write_numrecs(ncp);
  399. }
  400. }
  401. common_return:
  402. #ifdef LOCKNUMREC
  403. /* finished with our lock - increment serving number */
  404. (void) shmem_short_finc((shmem_t *) ncp->lock + LOCKNUMREC_SERVING,
  405. ncp->lock[LOCKNUMREC_BASEPE]);
  406. #endif
  407. return status;
  408. }
  409. /*
  410. * Check whether 'coord' values are valid for the variable.
  411. */
  412. static int
  413. NCcoordck(NC *ncp, const NC_var *varp, const size_t *coord)
  414. {
  415. const size_t *ip;
  416. size_t *up;
  417. if(varp->ndims == 0)
  418. return NC_NOERR; /* 'scalar' variable */
  419. if(IS_RECVAR(varp))
  420. {
  421. if(*coord > X_INT_MAX)
  422. return NC_EINVALCOORDS; /* sanity check */
  423. if(NC_readonly(ncp) && *coord >= NC_get_numrecs(ncp))
  424. {
  425. if(!NC_doNsync(ncp))
  426. return NC_EINVALCOORDS;
  427. /* else */
  428. {
  429. /* Update from disk and check again */
  430. const int status = read_numrecs(ncp);
  431. if(status != NC_NOERR)
  432. return status;
  433. if(*coord >= NC_get_numrecs(ncp))
  434. return NC_EINVALCOORDS;
  435. }
  436. }
  437. ip = coord + 1;
  438. up = varp->shape + 1;
  439. }
  440. else
  441. {
  442. ip = coord;
  443. up = varp->shape;
  444. }
  445. #ifdef CDEBUG
  446. fprintf(stderr," NCcoordck: coord %ld, count %d, ip %ld\n",
  447. coord, varp->ndims, ip );
  448. #endif /* CDEBUG */
  449. for(; ip < coord + varp->ndims; ip++, up++)
  450. {
  451. #ifdef CDEBUG
  452. fprintf(stderr," NCcoordck: ip %p, *ip %ld, up %p, *up %lu\n",
  453. ip, *ip, up, *up );
  454. #endif /* CDEBUG */
  455. /* cast needed for braindead systems with signed size_t */
  456. if((unsigned long) *ip >= (unsigned long) *up )
  457. return NC_EINVALCOORDS;
  458. }
  459. return NC_NOERR;
  460. }
  461. /*
  462. * Check whether 'edges' are valid for the variable and 'start'
  463. */
  464. /*ARGSUSED*/
  465. static int
  466. NCedgeck(const NC *ncp, const NC_var *varp,
  467. const size_t *start, const size_t *edges)
  468. {
  469. const size_t *const end = start + varp->ndims;
  470. const size_t *shp = varp->shape;
  471. if(varp->ndims == 0)
  472. return NC_NOERR; /* 'scalar' variable */
  473. if(IS_RECVAR(varp))
  474. {
  475. start++;
  476. edges++;
  477. shp++;
  478. }
  479. for(; start < end; start++, edges++, shp++)
  480. {
  481. /* cast needed for braindead systems with signed size_t */
  482. if((unsigned long) *edges > *shp ||
  483. (unsigned long) *start + (unsigned long) *edges > *shp)
  484. {
  485. return(NC_EEDGE);
  486. }
  487. }
  488. return NC_NOERR;
  489. }
  490. /*
  491. * Translate the (variable, coord) pair into a seek index
  492. */
  493. static off_t
  494. NC_varoffset(const NC *ncp, const NC_var *varp, const size_t *coord)
  495. {
  496. if(varp->ndims == 0) /* 'scalar' variable */
  497. return varp->begin;
  498. if(varp->ndims == 1)
  499. {
  500. if(IS_RECVAR(varp))
  501. return varp->begin +
  502. (off_t)(*coord) * (off_t)ncp->recsize;
  503. /* else */
  504. return varp->begin + (off_t)(*coord) * (off_t)varp->xsz;
  505. }
  506. /* else */
  507. {
  508. off_t lcoord = (off_t)coord[varp->ndims -1];
  509. size_t *up = varp->dsizes +1;
  510. const size_t *ip = coord;
  511. const size_t *const end = varp->dsizes + varp->ndims;
  512. if(IS_RECVAR(varp))
  513. up++, ip++;
  514. for(; up < end; up++, ip++)
  515. lcoord += *up * *ip;
  516. lcoord *= varp->xsz;
  517. if(IS_RECVAR(varp))
  518. lcoord += (off_t)(*coord) * ncp->recsize;
  519. lcoord += varp->begin;
  520. return lcoord;
  521. }
  522. }
  523. dnl
  524. dnl Output 'nelems' items of contiguous data of type "Type"
  525. dnl for variable 'varp' at 'start'.
  526. dnl "Xtype" had better match 'varp->type'.
  527. dnl---
  528. dnl
  529. dnl PUTNCVX(Xtype, Type)
  530. dnl
  531. define(`PUTNCVX',dnl
  532. `dnl
  533. static int
  534. putNCvx_$1_$2(NC *ncp, const NC_var *varp,
  535. const size_t *start, size_t nelems, const $2 *value)
  536. {
  537. off_t offset = NC_varoffset(ncp, varp, start);
  538. size_t remaining = varp->xsz * nelems;
  539. int status = NC_NOERR;
  540. void *xp;
  541. if(nelems == 0)
  542. return NC_NOERR;
  543. assert(value != NULL);
  544. for(;;)
  545. {
  546. size_t extent = MIN(remaining, ncp->chunk);
  547. size_t nput = ncx_howmany(varp->type, extent);
  548. int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
  549. RGN_WRITE, &xp);
  550. if(lstatus != NC_NOERR)
  551. return lstatus;
  552. lstatus = ncx_putn_$1_$2(&xp, nput, value);
  553. if(lstatus != NC_NOERR && status == NC_NOERR)
  554. {
  555. /* not fatal to the loop */
  556. status = lstatus;
  557. }
  558. (void) ncp->nciop->rel(ncp->nciop, offset,
  559. RGN_MODIFIED);
  560. remaining -= extent;
  561. if(remaining == 0)
  562. break; /* normal loop exit */
  563. offset += extent;
  564. value += nput;
  565. }
  566. return status;
  567. }
  568. ')dnl
  569. PUTNCVX(char, char)
  570. PUTNCVX(schar, schar)
  571. PUTNCVX(schar, uchar)
  572. PUTNCVX(schar, short)
  573. PUTNCVX(schar, int)
  574. PUTNCVX(schar, long)
  575. PUTNCVX(schar, float)
  576. PUTNCVX(schar, double)
  577. PUTNCVX(short, schar)
  578. PUTNCVX(short, uchar)
  579. PUTNCVX(short, short)
  580. PUTNCVX(short, int)
  581. PUTNCVX(short, long)
  582. PUTNCVX(short, float)
  583. PUTNCVX(short, double)
  584. PUTNCVX(int, schar)
  585. PUTNCVX(int, uchar)
  586. PUTNCVX(int, short)
  587. PUTNCVX(int, int)
  588. PUTNCVX(int, long)
  589. PUTNCVX(int, float)
  590. PUTNCVX(int, double)
  591. PUTNCVX(float, schar)
  592. PUTNCVX(float, uchar)
  593. PUTNCVX(float, short)
  594. PUTNCVX(float, int)
  595. PUTNCVX(float, long)
  596. PUTNCVX(float, float)
  597. PUTNCVX(float, double)
  598. PUTNCVX(double, schar)
  599. PUTNCVX(double, uchar)
  600. PUTNCVX(double, short)
  601. PUTNCVX(double, int)
  602. PUTNCVX(double, long)
  603. PUTNCVX(double, float)
  604. PUTNCVX(double, double)
  605. dnl
  606. dnl PUTNCV(Type)
  607. dnl
  608. define(`PUTNCV',dnl
  609. `dnl
  610. static int
  611. putNCv_$1(NC *ncp, const NC_var *varp,
  612. const size_t *start, size_t nelems, const $1 *value)
  613. {
  614. switch(varp->type){
  615. case NC_CHAR:
  616. return NC_ECHAR;
  617. case NC_BYTE:
  618. return putNCvx_schar_$1(ncp, varp, start, nelems,
  619. value);
  620. case NC_SHORT:
  621. return putNCvx_short_$1(ncp, varp, start, nelems,
  622. value);
  623. case NC_INT:
  624. return putNCvx_int_$1(ncp, varp, start, nelems,
  625. value);
  626. case NC_FLOAT:
  627. return putNCvx_float_$1(ncp, varp, start, nelems,
  628. value);
  629. case NC_DOUBLE:
  630. return putNCvx_double_$1(ncp, varp, start, nelems,
  631. value);
  632. }
  633. return NC_EBADTYPE;
  634. }
  635. ')dnl
  636. static int
  637. putNCv_text(NC *ncp, const NC_var *varp,
  638. const size_t *start, size_t nelems, const char *value)
  639. {
  640. if(varp->type != NC_CHAR)
  641. return NC_ECHAR;
  642. return putNCvx_char_char(ncp, varp, start, nelems, value);
  643. }
  644. PUTNCV(schar)
  645. PUTNCV(uchar)
  646. PUTNCV(short)
  647. PUTNCV(int)
  648. PUTNCV(long)
  649. PUTNCV(float)
  650. PUTNCV(double)
  651. dnl
  652. dnl GETNCVX(XType, Type)
  653. dnl
  654. define(`GETNCVX',dnl
  655. `dnl
  656. static int
  657. getNCvx_$1_$2(const NC *ncp, const NC_var *varp,
  658. const size_t *start, size_t nelems, $2 *value)
  659. {
  660. off_t offset = NC_varoffset(ncp, varp, start);
  661. size_t remaining = varp->xsz * nelems;
  662. int status = NC_NOERR;
  663. const void *xp;
  664. if(nelems == 0)
  665. return NC_NOERR;
  666. assert(value != NULL);
  667. for(;;)
  668. {
  669. size_t extent = MIN(remaining, ncp->chunk);
  670. size_t nget = ncx_howmany(varp->type, extent);
  671. int lstatus = ncp->nciop->get(ncp->nciop, offset, extent,
  672. 0, (void **)&xp); /* cast away const */
  673. if(lstatus != NC_NOERR)
  674. return lstatus;
  675. lstatus = ncx_getn_$1_$2(&xp, nget, value);
  676. if(lstatus != NC_NOERR && status == NC_NOERR)
  677. status = lstatus;
  678. (void) ncp->nciop->rel(ncp->nciop, offset, 0);
  679. remaining -= extent;
  680. if(remaining == 0)
  681. break; /* normal loop exit */
  682. offset += extent;
  683. value += nget;
  684. }
  685. return status;
  686. }
  687. ')dnl
  688. GETNCVX(char, char)
  689. GETNCVX(schar, schar)
  690. GETNCVX(schar, uchar)
  691. GETNCVX(schar, short)
  692. GETNCVX(schar, int)
  693. GETNCVX(schar, long)
  694. GETNCVX(schar, float)
  695. GETNCVX(schar, double)
  696. GETNCVX(short, schar)
  697. GETNCVX(short, uchar)
  698. GETNCVX(short, short)
  699. GETNCVX(short, int)
  700. GETNCVX(short, long)
  701. GETNCVX(short, float)
  702. GETNCVX(short, double)
  703. GETNCVX(int, schar)
  704. GETNCVX(int, uchar)
  705. GETNCVX(int, short)
  706. GETNCVX(int, int)
  707. GETNCVX(int, long)
  708. GETNCVX(int, float)
  709. GETNCVX(int, double)
  710. GETNCVX(float, schar)
  711. GETNCVX(float, uchar)
  712. GETNCVX(float, short)
  713. GETNCVX(float, int)
  714. GETNCVX(float, long)
  715. GETNCVX(float, float)
  716. GETNCVX(float, double)
  717. GETNCVX(double, schar)
  718. GETNCVX(double, uchar)
  719. GETNCVX(double, short)
  720. GETNCVX(double, int)
  721. GETNCVX(double, long)
  722. GETNCVX(double, float)
  723. GETNCVX(double, double)
  724. dnl
  725. dnl GETNCV(Type)
  726. dnl
  727. define(`GETNCV',dnl
  728. `dnl
  729. static int
  730. getNCv_$1(const NC *ncp, const NC_var *varp,
  731. const size_t *start, size_t nelems, $1 *value)
  732. {
  733. switch(varp->type){
  734. case NC_CHAR:
  735. return NC_ECHAR;
  736. case NC_BYTE:
  737. return getNCvx_schar_$1(ncp, varp, start, nelems,
  738. value);
  739. case NC_SHORT:
  740. return getNCvx_short_$1(ncp, varp, start, nelems,
  741. value);
  742. case NC_INT:
  743. return getNCvx_int_$1(ncp, varp, start, nelems,
  744. value);
  745. case NC_FLOAT:
  746. return getNCvx_float_$1(ncp, varp, start, nelems,
  747. value);
  748. case NC_DOUBLE:
  749. return getNCvx_double_$1(ncp, varp, start, nelems,
  750. value);
  751. }
  752. return NC_EBADTYPE;
  753. }
  754. ')dnl
  755. GETNCV(schar)
  756. GETNCV(uchar)
  757. GETNCV(short)
  758. GETNCV(int)
  759. GETNCV(long)
  760. GETNCV(float)
  761. GETNCV(double)
  762. static int
  763. getNCv_text(const NC *ncp, const NC_var *varp,
  764. const size_t *start, size_t nelems, char *value)
  765. {
  766. if(varp->type != NC_CHAR)
  767. return NC_ECHAR;
  768. return getNCvx_char_char(ncp, varp, start, nelems, value);
  769. }
  770. /*
  771. * Copy 'nbytes' contiguous external values
  772. * from ('inncp', invp', inncoord')
  773. * to ('outncp', 'outvp', 'outcoord')
  774. * 'inncp' shouldn't be the same as 'outncp'.
  775. * Used only by ncvarcopy()
  776. */
  777. static int
  778. NCxvarcpy(NC *inncp, NC_var *invp, size_t *incoord,
  779. NC *outncp, NC_var *outvp, size_t *outcoord, size_t nbytes)
  780. {
  781. int status;
  782. off_t inoffset = NC_varoffset(inncp, invp, incoord);
  783. off_t outoffset = NC_varoffset(outncp, outvp, outcoord);
  784. void *inxp;
  785. void *outxp;
  786. const size_t chunk = MIN(inncp->chunk, outncp->chunk);
  787. do {
  788. const size_t extent = MIN(nbytes, chunk);
  789. status = inncp->nciop->get(inncp->nciop, inoffset, extent,
  790. 0, &inxp);
  791. if(status != NC_NOERR)
  792. return status;
  793. status = outncp->nciop->get(outncp->nciop, outoffset, extent,
  794. RGN_WRITE, &outxp);
  795. if(status != NC_NOERR)
  796. {
  797. (void) inncp->nciop->rel(inncp->nciop, inoffset, 0);
  798. break;
  799. }
  800. (void) memcpy(outxp, inxp, extent);
  801. status = outncp->nciop->rel(outncp->nciop, outoffset,
  802. RGN_MODIFIED);
  803. (void) inncp->nciop->rel(inncp->nciop, inoffset, 0);
  804. nbytes -= extent;
  805. if(nbytes == 0)
  806. break; /* normal loop exit */
  807. inoffset += extent;
  808. outoffset += extent;
  809. } while (status == NC_NOERR);
  810. return status;
  811. }
  812. /*
  813. * For ncvar{put,get},
  814. * find the largest contiguous block from within 'edges'.
  815. * returns the index to the left of this (which may be -1).
  816. * Compute the number of contiguous elements and return
  817. * that in *iocountp.
  818. * The presence of "record" variables makes this routine
  819. * overly subtle.
  820. */
  821. static int
  822. NCiocount(const NC *const ncp, const NC_var *const varp,
  823. const size_t *const edges,
  824. size_t *const iocountp)
  825. {
  826. const size_t *edp0 = edges;
  827. const size_t *edp = edges + varp->ndims;
  828. const size_t *shp = varp->shape + varp->ndims;
  829. if(IS_RECVAR(varp))
  830. {
  831. if(varp->ndims == 1 && ncp->recsize <= varp->len)
  832. {
  833. /* one dimensional && the only 'record' variable */
  834. *iocountp = *edges;
  835. return(0);
  836. }
  837. /* else */
  838. edp0++;
  839. }
  840. assert(edges != NULL);
  841. /* find max contiguous */
  842. while(edp > edp0)
  843. {
  844. shp--; edp--;
  845. if(*edp < *shp )
  846. {
  847. const size_t *zedp = edp;
  848. while(zedp >= edp0)
  849. {
  850. if(*zedp == 0)
  851. {
  852. *iocountp = 0;
  853. goto done;
  854. }
  855. /* Tip of the hat to segmented architectures */
  856. if(zedp == edp0)
  857. break;
  858. zedp--;
  859. }
  860. break;
  861. }
  862. assert(*edp == *shp);
  863. }
  864. /*
  865. * edp, shp reference rightmost index s.t. *(edp +1) == *(shp +1)
  866. *
  867. * Or there is only one dimension.
  868. * If there is only one dimension and it is 'non record' dimension,
  869. * edp is &edges[0] and we will return -1.
  870. * If there is only one dimension and and it is a "record dimension",
  871. * edp is &edges[1] (out of bounds) and we will return 0;
  872. */
  873. assert(shp >= varp->shape + varp->ndims -1
  874. || *(edp +1) == *(shp +1));
  875. /* now accumulate max count for a single io operation */
  876. for(*iocountp = 1, edp0 = edp;
  877. edp0 < edges + varp->ndims;
  878. edp0++)
  879. {
  880. *iocountp *= *edp0;
  881. }
  882. done:
  883. return((int)(edp - edges) - 1);
  884. }
  885. /*
  886. * Set the elements of the array 'upp' to
  887. * the sum of the corresponding elements of
  888. * 'stp' and 'edp'. 'end' should be &stp[nelems].
  889. */
  890. static void
  891. set_upper(size_t *upp, /* modified on return */
  892. const size_t *stp,
  893. const size_t *edp,
  894. const size_t *const end)
  895. {
  896. while(upp < end) {
  897. *upp++ = *stp++ + *edp++;
  898. }
  899. }
  900. /*
  901. * The infamous and oft-discussed odometer code.
  902. *
  903. * 'start[]' is the starting coordinate.
  904. * 'upper[]' is the upper bound s.t. start[ii] < upper[ii].
  905. * 'coord[]' is the register, the current coordinate value.
  906. * For some ii,
  907. * upp == &upper[ii]
  908. * cdp == &coord[ii]
  909. *
  910. * Running this routine increments *cdp.
  911. *
  912. * If after the increment, *cdp is equal to *upp
  913. * (and cdp is not the leftmost dimension),
  914. * *cdp is "zeroed" to the starting value and
  915. * we need to "carry", eg, increment one place to
  916. * the left.
  917. *
  918. * TODO: Some architectures hate recursion?
  919. * Reimplement non-recursively.
  920. */
  921. static void
  922. odo1(const size_t *const start, const size_t *const upper,
  923. size_t *const coord, /* modified on return */
  924. const size_t *upp,
  925. size_t *cdp)
  926. {
  927. assert(coord <= cdp && cdp <= coord + NC_MAX_VAR_DIMS);
  928. assert(upper <= upp && upp <= upper + NC_MAX_VAR_DIMS);
  929. assert(upp - upper == cdp - coord);
  930. assert(*cdp <= *upp);
  931. (*cdp)++;
  932. if(cdp != coord && *cdp >= *upp)
  933. {
  934. *cdp = start[cdp - coord];
  935. odo1(start, upper, coord, upp -1, cdp -1);
  936. }
  937. }
  938. #ifdef _CRAYC
  939. #pragma _CRI noinline odo1
  940. #endif
  941. dnl
  942. dnl NCTEXTCOND(Abbrv)
  943. dnl This is used inside the NC{PUT,GET} macros below
  944. dnl
  945. define(`NCTEXTCOND',dnl
  946. `dnl
  947. ifelse($1, text,dnl
  948. `dnl
  949. if(varp->type != NC_CHAR)
  950. return NC_ECHAR;
  951. ',dnl
  952. `dnl
  953. if(varp->type == NC_CHAR)
  954. return NC_ECHAR;
  955. ')dnl
  956. ')dnl
  957. /* Public */
  958. dnl
  959. dnl NCPUTVAR1(Abbrev, Type)
  960. dnl
  961. define(`NCPUTVAR1',dnl
  962. `dnl
  963. int
  964. nc_put_var1_$1(int ncid, int varid, const size_t *coord,
  965. const $2 *value)
  966. {
  967. int status;
  968. NC *ncp;
  969. const NC_var *varp;
  970. status = NC_check_id(ncid, &ncp);
  971. if(status != NC_NOERR)
  972. return status;
  973. if(NC_readonly(ncp))
  974. return NC_EPERM;
  975. if(NC_indef(ncp))
  976. return NC_EINDEFINE;
  977. varp = NC_lookupvar(ncp, varid);
  978. if(varp == NULL)
  979. return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
  980. NCTEXTCOND($1)
  981. status = NCcoordck(ncp, varp, coord);
  982. if(status != NC_NOERR)
  983. return status;
  984. if(IS_RECVAR(varp))
  985. {
  986. status = NCvnrecs(ncp, *coord +1);
  987. if(status != NC_NOERR)
  988. return status;
  989. }
  990. return putNCv_$1(ncp, varp, coord, 1, value);
  991. }
  992. ')dnl
  993. NCPUTVAR1(text, char)
  994. NCPUTVAR1(uchar, uchar)
  995. NCPUTVAR1(schar, schar)
  996. NCPUTVAR1(short, short)
  997. NCPUTVAR1(int, int)
  998. NCPUTVAR1(long, long)
  999. NCPUTVAR1(float, float)
  1000. NCPUTVAR1(double, double)
  1001. dnl
  1002. dnl NCGETVAR1(Abbrv, Type)
  1003. dnl
  1004. define(`NCGETVAR1',dnl
  1005. `dnl
  1006. int
  1007. nc_get_var1_$1(int ncid, int varid, const size_t *coord, $2 *value)
  1008. {
  1009. int status;
  1010. NC *ncp;
  1011. const NC_var *varp;
  1012. status = NC_check_id(ncid, &ncp);
  1013. if(status != NC_NOERR)
  1014. return status;
  1015. if(NC_indef(ncp))
  1016. return NC_EINDEFINE;
  1017. varp = NC_lookupvar(ncp, varid);
  1018. if(varp == NULL)
  1019. return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
  1020. NCTEXTCOND($1)
  1021. status = NCcoordck(ncp, varp, coord);
  1022. if(status != NC_NOERR)
  1023. return status;
  1024. return getNCv_$1(ncp, varp, coord, 1, value);
  1025. }
  1026. ')dnl
  1027. NCGETVAR1(text, char)
  1028. NCGETVAR1(uchar, uchar)
  1029. NCGETVAR1(schar, schar)
  1030. NCGETVAR1(short, short)
  1031. NCGETVAR1(int, int)
  1032. NCGETVAR1(long, long)
  1033. NCGETVAR1(float, float)
  1034. NCGETVAR1(double, double)
  1035. dnl
  1036. dnl NCPUTVARA(Abbrv, Type)
  1037. dnl
  1038. define(`NCPUTVARA',dnl
  1039. `dnl
  1040. int
  1041. nc_put_vara_$1(int ncid, int varid,
  1042. const size_t *start, const size_t *edges, const $2 *value)
  1043. {
  1044. int status = NC_NOERR;
  1045. NC *ncp;
  1046. const NC_var *varp;
  1047. int ii;
  1048. size_t iocount;
  1049. status = NC_check_id(ncid, &ncp);
  1050. if(status != NC_NOERR)
  1051. return status;
  1052. if(NC_readonly(ncp))
  1053. return NC_EPERM;
  1054. if(NC_indef(ncp))
  1055. return NC_EINDEFINE;
  1056. varp = NC_lookupvar(ncp, varid);
  1057. if(varp == NULL)
  1058. return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
  1059. NCTEXTCOND($1)
  1060. status = NCcoordck(ncp, varp, start);
  1061. if(status != NC_NOERR)
  1062. return status;
  1063. status = NCedgeck(ncp, varp, start, edges);
  1064. if(status != NC_NOERR)
  1065. return status;
  1066. if(varp->ndims == 0) /* scalar variable */
  1067. {
  1068. return( putNCv_$1(ncp, varp, start, 1, value) );
  1069. }
  1070. if(IS_RECVAR(varp))
  1071. {
  1072. status = NCvnrecs(ncp, *start + *edges);
  1073. if(status != NC_NOERR)
  1074. return status;
  1075. if(varp->ndims == 1
  1076. && ncp->recsize <= varp->len)
  1077. {
  1078. /* one dimensional && the only record variable */
  1079. return( putNCv_$1(ncp, varp, start, *edges, value) );
  1080. }
  1081. }
  1082. /*
  1083. * find max contiguous
  1084. * and accumulate max count for a single io operation
  1085. */
  1086. ii = NCiocount(ncp, varp, edges, &iocount);
  1087. if(ii == -1)
  1088. {
  1089. return( putNCv_$1(ncp, varp, start, iocount, value) );
  1090. }
  1091. assert(ii >= 0);
  1092. { /* inline */
  1093. ALLOC_ONSTACK(coord, size_t, varp->ndims);
  1094. ALLOC_ONSTACK(upper, size_t, varp->ndims);
  1095. const size_t index = ii;
  1096. /* copy in starting indices */
  1097. (void) memcpy(coord, start, varp->ndims * sizeof(size_t));
  1098. /* set up in maximum indices */
  1099. set_upper(upper, start, edges, &upper[varp->ndims]);
  1100. /* ripple counter */
  1101. while(*coord < *upper)
  1102. {
  1103. const int lstatus = putNCv_$1(ncp, varp, coord, iocount,
  1104. value);
  1105. if(lstatus != NC_NOERR)
  1106. {
  1107. if(lstatus != NC_ERANGE)
  1108. {
  1109. status = lstatus;
  1110. /* fatal for the loop */
  1111. break;
  1112. }
  1113. /* else NC_ERANGE, not fatal for the loop */
  1114. if(status == NC_NOERR)
  1115. status = lstatus;
  1116. }
  1117. value += iocount;
  1118. odo1(start, upper, coord, &upper[index], &coord[index]);
  1119. }
  1120. FREE_ONSTACK(upper);
  1121. FREE_ONSTACK(coord);
  1122. } /* end inline */
  1123. return status;
  1124. }
  1125. ')dnl
  1126. NCPUTVARA(text, char)
  1127. NCPUTVARA(uchar, uchar)
  1128. NCPUTVARA(schar, schar)
  1129. NCPUTVARA(short, short)
  1130. NCPUTVARA(int, int)
  1131. NCPUTVARA(long, long)
  1132. NCPUTVARA(float, float)
  1133. NCPUTVARA(double, double)
  1134. dnl
  1135. dnl NCGETVARA(Abbrv, Type)
  1136. dnl
  1137. define(`NCGETVARA',dnl
  1138. `dnl
  1139. int
  1140. nc_get_vara_$1(int ncid, int varid,
  1141. const size_t *start, const size_t *edges, $2 *value)
  1142. {
  1143. int status = NC_NOERR;
  1144. NC *ncp;
  1145. const NC_var *varp;
  1146. int ii;
  1147. size_t iocount;
  1148. status = NC_check_id(ncid, &ncp);
  1149. if(status != NC_NOERR)
  1150. return status;
  1151. if(NC_indef(ncp))
  1152. return NC_EINDEFINE;
  1153. varp = NC_lookupvar(ncp, varid);
  1154. if(varp == NULL)
  1155. return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
  1156. NCTEXTCOND($1)
  1157. status = NCcoordck(ncp, varp, start);
  1158. if(status != NC_NOERR)
  1159. return status;
  1160. status = NCedgeck(ncp, varp, start, edges);
  1161. if(status != NC_NOERR)
  1162. return status;
  1163. if(varp->ndims == 0) /* scalar variable */
  1164. {
  1165. return( getNCv_$1(ncp, varp, start, 1, value) );
  1166. }
  1167. if(IS_RECVAR(varp))
  1168. {
  1169. if(*start + *edges > NC_get_numrecs(ncp))
  1170. return NC_EEDGE;
  1171. if(varp->ndims == 1 && ncp->recsize <= varp->len)
  1172. {
  1173. /* one dimensional && the only record variable */
  1174. return( getNCv_$1(ncp, varp, start, *edges, value) );
  1175. }
  1176. }
  1177. /*
  1178. * find max contiguous
  1179. * and accumulate max count for a single io operation
  1180. */
  1181. ii = NCiocount(ncp, varp, edges, &iocount);
  1182. if(ii == -1)
  1183. {
  1184. return( getNCv_$1(ncp, varp, start, iocount, value) );
  1185. }
  1186. assert(ii >= 0);
  1187. { /* inline */
  1188. ALLOC_ONSTACK(coord, size_t, varp->ndims);
  1189. ALLOC_ONSTACK(upper, size_t, varp->ndims);
  1190. const size_t index = ii;
  1191. /* copy in starting indices */
  1192. (void) memcpy(coord, start, varp->ndims * sizeof(size_t));
  1193. /* set up in maximum indices */
  1194. set_upper(upper, start, edges, &upper[varp->ndims]);
  1195. /* ripple counter */
  1196. while(*coord < *upper)
  1197. {
  1198. const int lstatus = getNCv_$1(ncp, varp, coord, iocount,
  1199. value);
  1200. if(lstatus != NC_NOERR)
  1201. {
  1202. if(lstatus != NC_ERANGE)
  1203. {
  1204. status = lstatus;
  1205. /* fatal for the loop */
  1206. break;
  1207. }
  1208. /* else NC_ERANGE, not fatal for the loop */
  1209. if(status == NC_NOERR)
  1210. status = lstatus;
  1211. }
  1212. value += iocount;
  1213. odo1(start, upper, coord, &upper[index], &coord[index]);
  1214. }
  1215. FREE_ONSTACK(upper);
  1216. FREE_ONSTACK(coord);
  1217. } /* end inline */
  1218. return status;
  1219. }
  1220. ')dnl
  1221. NCGETVARA(text, char)
  1222. NCGETVARA(uchar, uchar)
  1223. NCGETVARA(schar, schar)
  1224. NCGETVARA(short, short)
  1225. NCGETVARA(int, int)
  1226. NCGETVARA(long, long)
  1227. NCGETVARA(float, float)
  1228. NCGETVARA(double, double)
  1229. #if defined(__cplusplus)
  1230. /* C++ consts default to internal linkage and must be initialized */
  1231. const size_t coord_zero[NC_MAX_VAR_DIMS] = {0};
  1232. #else
  1233. static const size_t coord_zero[NC_MAX_VAR_DIMS];
  1234. #endif
  1235. dnl
  1236. dnl NCPUTVAR(Abbrev, Type)
  1237. dnl
  1238. define(`NCPUTVAR',dnl
  1239. `dnl
  1240. int
  1241. nc_put_var_$1(int ncid, int varid, const $2 *value)
  1242. {
  1243. int status = NC_NOERR;
  1244. NC *ncp;
  1245. const NC_var *varp;
  1246. status = NC_check_id(ncid, &ncp);
  1247. if(status != NC_NOERR)
  1248. return status;
  1249. if(NC_readonly(ncp))
  1250. return NC_EPERM;
  1251. if(NC_indef(ncp))
  1252. return NC_EINDEFINE;
  1253. varp = NC_lookupvar(ncp, varid);
  1254. if(varp == NULL)
  1255. return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
  1256. NCTEXTCOND($1)
  1257. if(varp->ndims == 0) /* scalar variable */
  1258. {
  1259. const size_t zed = 0;
  1260. return( putNCv_$1(ncp, varp, &zed, 1, value) );
  1261. }
  1262. if(!IS_RECVAR(varp))
  1263. {
  1264. return(putNCv_$1(ncp, varp, coord_zero, *varp->dsizes, value));
  1265. }
  1266. /* else */
  1267. if(varp->ndims == 1
  1268. && ncp->recsize <= varp->len)
  1269. {
  1270. /* one dimensional && the only record variable */
  1271. return(putNCv_$1(ncp, varp, coord_zero, NC_get_numrecs(ncp),
  1272. value));
  1273. }
  1274. /* else */
  1275. {
  1276. ALLOC_ONSTACK(coord, size_t, varp->ndims);
  1277. size_t elemsPerRec = 1;
  1278. const size_t nrecs = NC_get_numrecs(ncp);
  1279. (void) memset(coord, 0, varp->ndims * sizeof(size_t));
  1280. /* TODO: fix dsizes to avoid this nonsense */
  1281. if(varp->ndims > 1)
  1282. elemsPerRec = varp->dsizes[1];
  1283. while(*coord < nrecs)
  1284. {
  1285. const int lstatus = putNCv_$1(ncp, varp, coord, elemsPerRec,
  1286. value);
  1287. if(lstatus != NC_NOERR)
  1288. {
  1289. if(lstatus != NC_ERANGE)
  1290. {
  1291. status = lstatus;
  1292. /* fatal for the loop */
  1293. break;
  1294. }
  1295. /* else NC_ERANGE, not fatal for the loop */
  1296. if(status == NC_NOERR)
  1297. status = lstatus;
  1298. }
  1299. value += elemsPerRec;
  1300. (*coord)++;
  1301. }
  1302. FREE_ONSTACK(coord);
  1303. } /* elemsPerRec */
  1304. return status;
  1305. }
  1306. ')dnl
  1307. NCPUTVAR(text, char)
  1308. NCPUTVAR(uchar, uchar)
  1309. NCPUTVAR(schar, schar)
  1310. NCPUTVAR(short, short)
  1311. NCPUTVAR(int, int)
  1312. NCPUTVAR(long, long)
  1313. NCPUTVAR(float, float)
  1314. NCPUTVAR(double, double)
  1315. dnl
  1316. dnl NCGETVAR(Abbrv, Type)
  1317. dnl
  1318. define(`NCGETVAR',dnl
  1319. `dnl
  1320. int
  1321. nc_get_var_$1(int ncid, int varid, $2 *value)
  1322. {
  1323. int status = NC_NOERR;
  1324. NC *ncp;
  1325. const NC_var *varp;
  1326. status = NC_check_id(ncid, &ncp);
  1327. if(status != NC_NOERR)
  1328. return status;
  1329. if(NC_indef(ncp))
  1330. return NC_EINDEFINE;
  1331. varp = NC_lookupvar(ncp, varid);
  1332. if(varp == NULL)
  1333. return NC_ENOTVAR; /* TODO: lost NC_EGLOBAL */
  1334. if(varp->ndims == 0) /* scalar variable */
  1335. {
  1336. const size_t zed = 0;
  1337. return( getNCv_$1(ncp, varp, &zed, 1, value) );
  1338. }
  1339. NCTEXTCOND($1)
  1340. if(!IS_RECVAR(varp))
  1341. {
  1342. return(getNCv_$1(ncp, varp, coord_zero, *varp->dsizes, value));
  1343. }
  1344. /* else */
  1345. if(varp->ndims == 1
  1346. && ncp->recsize <= varp->len)
  1347. {
  1348. /* one dimensional && the only record variable */
  1349. return(getNCv_$1(ncp, varp, coord_zero, NC_get_numrecs(ncp),
  1350. value));
  1351. }
  1352. /* else */
  1353. {
  1354. ALLOC_ONSTACK(coord, size_t, varp->ndims);
  1355. size_t elemsPerRec = 1;
  1356. const size_t nrecs = NC_get_numrecs(ncp);
  1357. (void) memset(coord, 0, varp->ndims * sizeof(size_t));
  1358. /* TODO: fix dsizes to avoid this nonsense */
  1359. if(varp->ndims > 1)
  1360. elemsPerRec = varp->dsizes[1];
  1361. while(*coord < nrecs)
  1362. {
  1363. const int lstatus = getNCv_$1(ncp, varp, coord, elemsPerRec,
  1364. value);
  1365. if(lstatus != NC_NOERR)
  1366. {
  1367. if(lstatus != NC_ERANGE)
  1368. {
  1369. status = lstatus;
  1370. /* fatal for the loop */
  1371. break;
  1372. }
  1373. /* else NC_ERANGE, not fatal for the loop */
  1374. if(status == NC_NOERR)
  1375. status = lstatus;
  1376. }
  1377. value += elemsPerRec;
  1378. (*coord)++;
  1379. }
  1380. FREE_ONSTACK(coord);
  1381. } /* elemsPerRec */
  1382. return status;
  1383. }
  1384. ')dnl
  1385. NCGETVAR(text, char)
  1386. NCGETVAR(uchar, uchar)
  1387. NCGETVAR(schar, schar)
  1388. NCGETVAR(short, short)
  1389. NCGETVAR(int, int)
  1390. NCGETVAR(long, long)
  1391. NCGETVAR(float, float)
  1392. NCGETVAR(double, double)
  1393. /* Begin putgetg.c */
  1394. dnl
  1395. dnl NC_VARM_Upper_Body(void)
  1396. dnl
  1397. define(`NC_VARM_Upper_Body',dnl
  1398. `dnl
  1399. int status = ENOERR;
  1400. NC *ncp;
  1401. NC_var *varp;
  1402. int maxidim; /* maximum dimensional index */
  1403. status = NC_check_id (ncid, &ncp);
  1404. if (status != NC_NOERR)
  1405. return status;
  1406. if (NC_indef (ncp))
  1407. {
  1408. return NC_EINDEFINE;
  1409. }
  1410. ')dnl
  1411. dnl
  1412. dnl NC_VARM_Mid_Body(put_or_get, Abbrv)
  1413. dnl
  1414. define(`NC_VARM_Mid_Body',dnl
  1415. `dnl
  1416. varp = NC_lookupvar (ncp, varid);
  1417. if (varp == NULL)
  1418. return NC_ENOTVAR;
  1419. NCTEXTCOND($2)
  1420. maxidim = (int) varp->ndims - 1;
  1421. if (maxidim < 0)
  1422. {
  1423. /*
  1424. * The variable is a scalar; consequently,
  1425. * there s only one thing to get and only one place to put it.
  1426. * (Why was I called?)
  1427. */
  1428. return $1 (ncp, varp, start, 1, value);
  1429. }
  1430. /*
  1431. * else
  1432. * The variable is an array.
  1433. */
  1434. {
  1435. int idim;
  1436. size_t *mystart = NULL;
  1437. size_t *myedges;
  1438. size_t *iocount; /* count vector */
  1439. size_t *stop; /* stop indexes */
  1440. size_t *length; /* edge lengths in bytes */
  1441. ptrdiff_t *mystride;
  1442. ptrdiff_t *mymap;
  1443. /*
  1444. * Verify stride argument.
  1445. */
  1446. for (idim = 0; idim <= maxidim; ++idim)
  1447. {
  1448. if (stride != NULL
  1449. && (stride[idim] == 0
  1450. /* cast needed for braindead systems with signed size_t */
  1451. || (unsigned long) stride[idim] >= X_INT_MAX))
  1452. {
  1453. return NC_ESTRIDE;
  1454. }
  1455. }
  1456. /* assert(sizeof(ptrdiff_t) >= sizeof(size_t)); */
  1457. mystart = (size_t *)calloc(varp->ndims * 7, sizeof(ptrdiff_t));
  1458. if(mystart == NULL)
  1459. return NC_ENOMEM;
  1460. myedges = mystart + varp->ndims;
  1461. iocount = myedges + varp->ndims;
  1462. stop = iocount + varp->ndims;
  1463. length = stop + varp->ndims;
  1464. mystride = (ptrdiff_t *)(length + varp->ndims);
  1465. mymap = mystride + varp->ndims;
  1466. /*
  1467. * Initialize I/O parameters.
  1468. */
  1469. for (idim = maxidim; idim >= 0; --idim)
  1470. {
  1471. mystart[idim] = start != NULL
  1472. ? start[idim]
  1473. : 0;
  1474. if (edges[idim] == 0)
  1475. {
  1476. status = NC_NOERR; /* read/write no data */
  1477. goto done;
  1478. }
  1479. myedges[idim] = edges != NULL
  1480. ? edges[idim]
  1481. : idim == 0 && IS_RECVAR (varp)
  1482. ? NC_get_numrecs(ncp) - mystart[idim]
  1483. : varp->shape[idim] - mystart[idim];
  1484. mystride[idim] = stride != NULL
  1485. ? stride[idim]
  1486. : 1;
  1487. mymap[idim] = map != NULL
  1488. ? map[idim]
  1489. : idim == maxidim
  1490. ? 1
  1491. : mymap[idim + 1] * (ptrdiff_t) myedges[idim + 1];
  1492. iocount[idim] = 1;
  1493. length[idim] = mymap[idim] * myedges[idim];
  1494. stop[idim] = mystart[idim] + myedges[idim] * mystride[idim];
  1495. }
  1496. ')dnl
  1497. dnl
  1498. dnl NC_VARM_Lower_Body(put_or_get)
  1499. dnl
  1500. define(`NC_VARM_Lower_Body',dnl
  1501. `dnl
  1502. /*
  1503. * As an optimization, adjust I/O parameters when the fastest
  1504. * dimension has unity stride both externally and internally.
  1505. * In this case, the user could have called a simpler routine
  1506. * (i.e. ncvar$1()
  1507. */
  1508. if (mystride[maxidim] == 1
  1509. && mymap[maxidim] == 1)
  1510. {
  1511. iocount[maxidim] = myedges[maxidim];
  1512. mystride[maxidim] = (ptrdiff_t) myedges[maxidim];
  1513. mymap[maxidim] = (ptrdiff_t) length[maxidim];
  1514. }
  1515. /*
  1516. * Perform I/O. Exit when done.
  1517. */
  1518. for (;;)
  1519. {
  1520. /* TODO: */
  1521. int lstatus = $1 (ncid, varid, mystart, iocount,
  1522. value);
  1523. if (lstatus != NC_NOERR
  1524. && (status == NC_NOERR || lstatus != NC_ERANGE))
  1525. status = lstatus;
  1526. /*
  1527. * The following code permutes through the variable s
  1528. * external start-index space and it s internal address
  1529. * space. At the UPC, this algorithm is commonly
  1530. * called "odometer code".
  1531. */
  1532. idim = maxidim;
  1533. carry:
  1534. value += mymap[idim];
  1535. mystart[idim] += mystride[idim];
  1536. if (mystart[idim] == stop[idim])
  1537. {
  1538. mystart[idim] = start[idim];
  1539. value -= length[idim];
  1540. if (--idim < 0)
  1541. break; /* normal return */
  1542. goto carry;
  1543. }
  1544. } /* I/O loop */
  1545. done:
  1546. free(mystart);
  1547. } /* variable is array */
  1548. return status;
  1549. ')dnl
  1550. dnl
  1551. dnl NCGETVARS(Abbrv, Type)
  1552. dnl
  1553. define(`NCGETVARS',dnl
  1554. `dnl
  1555. int
  1556. nc_get_vars_$1 (
  1557. int ncid,
  1558. int varid,
  1559. const size_t * start,
  1560. const size_t * edges,
  1561. const ptrdiff_t * stride,
  1562. $2 *value)
  1563. {
  1564. return nc_get_varm_$1 (ncid, varid, start, edges,
  1565. stride, 0, value);
  1566. }
  1567. ')dnl
  1568. NCGETVARS(text, char)
  1569. NCGETVARS(uchar, uchar)
  1570. NCGETVARS(schar, schar)
  1571. NCGETVARS(short, short)
  1572. NCGETVARS(int, int)
  1573. NCGETVARS(long, long)
  1574. NCGETVARS(float, float)
  1575. NCGETVARS(double, double)
  1576. dnl
  1577. dnl NCPUTVARS(Abbrv, Type)
  1578. dnl
  1579. define(`NCPUTVARS',dnl
  1580. `dnl
  1581. int
  1582. nc_put_vars_$1 (
  1583. int ncid,
  1584. int varid,
  1585. const size_t * start,
  1586. const size_t * edges,
  1587. const ptrdiff_t * stride,
  1588. const $2 *value)
  1589. {
  1590. return nc_put_varm_$1 (ncid, varid, start, edges,
  1591. stride, 0, value);
  1592. }
  1593. ')dnl
  1594. NCPUTVARS(text, char)
  1595. NCPUTVARS(uchar, uchar)
  1596. NCPUTVARS(schar, schar)
  1597. NCPUTVARS(short, short)
  1598. NCPUTVARS(int, int)
  1599. NCPUTVARS(long, long)
  1600. NCPUTVARS(float, float)
  1601. NCPUTVARS(double, double)
  1602. /*
  1603. * Generalized hyperslab input.
  1604. */
  1605. dnl
  1606. dnl NCGETVARM(Abbrv, Type)
  1607. dnl
  1608. define(`NCGETVARM',dnl
  1609. `dnl
  1610. int
  1611. nc_get_varm_$1(int ncid, int varid,
  1612. const size_t *start, const size_t *edges,
  1613. const ptrdiff_t *stride,
  1614. const ptrdiff_t *map,
  1615. $2 *value)
  1616. {
  1617. NC_VARM_Upper_Body()
  1618. NC_VARM_Mid_Body(getNCv_$1, $1)
  1619. /*
  1620. * Check start, edges
  1621. */
  1622. for (idim = maxidim; idim >= 0; --idim)
  1623. {
  1624. size_t dimlen =
  1625. idim == 0 && IS_RECVAR (varp)
  1626. ? NC_get_numrecs(ncp)
  1627. : varp->shape[idim];
  1628. if (mystart[idim] >= dimlen)
  1629. {
  1630. status = NC_EINVALCOORDS;
  1631. goto done;
  1632. }
  1633. if (mystart[idim] + myedges[idim] > dimlen)
  1634. {
  1635. status = NC_EEDGE;
  1636. goto done;
  1637. }
  1638. }
  1639. NC_VARM_Lower_Body(nc_get_vara_$1)
  1640. }
  1641. ')dnl
  1642. NCGETVARM(text, char)
  1643. NCGETVARM(uchar, uchar)
  1644. NCGETVARM(schar, schar)
  1645. NCGETVARM(short, short)
  1646. NCGETVARM(int, int)
  1647. NCGETVARM(long, long)
  1648. NCGETVARM(float, float)
  1649. NCGETVARM(double, double)
  1650. #ifdef NO_NETCDF_2
  1651. extern int
  1652. nctypelen(nc_type datatype);
  1653. #endif
  1654. /*
  1655. * Generalized hyperslab output.
  1656. */
  1657. dnl
  1658. dnl NCPUTVARM(Abbrv, Type)
  1659. dnl
  1660. define(`NCPUTVARM',dnl
  1661. `dnl
  1662. int
  1663. nc_put_varm_$1(int ncid, int varid,
  1664. const size_t *start, const size_t *edges,
  1665. const ptrdiff_t *stride, const ptrdiff_t *map,
  1666. const $2 *value)
  1667. {
  1668. NC_VARM_Upper_Body()
  1669. if (NC_readonly (ncp))
  1670. return NC_EPERM;
  1671. NC_VARM_Mid_Body(putNCv_$1, $1)
  1672. /*
  1673. * Check start, edges
  1674. */
  1675. for (idim = IS_RECVAR (varp); idim < maxidim; ++idim)
  1676. {
  1677. if (mystart[idim] > varp->shape[idim])
  1678. {
  1679. status = NC_EINVALCOORDS;
  1680. goto done;
  1681. }
  1682. if (mystart[idim] + myedges[idim] > varp->shape[idim])
  1683. {
  1684. status = NC_EEDGE;
  1685. goto done;
  1686. }
  1687. }
  1688. NC_VARM_Lower_Body(nc_put_vara_$1)
  1689. }
  1690. ')dnl
  1691. NCPUTVARM(text, char)
  1692. NCPUTVARM(uchar, uchar)
  1693. NCPUTVARM(schar, schar)
  1694. NCPUTVARM(short, short)
  1695. NCPUTVARM(int, int)
  1696. NCPUTVARM(long, long)
  1697. NCPUTVARM(float, float)
  1698. NCPUTVARM(double, double)
  1699. /*
  1700. * Copy the values of a variable from an input netCDF to an output netCDF.
  1701. * Input and output var assummed to have the same shape.
  1702. * return -1 on error.
  1703. */
  1704. int
  1705. nc_copy_var(int ncid_in, int varid, int ncid_out)
  1706. {
  1707. int status = NC_NOERR;
  1708. NC *inncp, *outncp;
  1709. NC_var *invp, *outvp;
  1710. status = NC_check_id(ncid_in, &inncp);
  1711. if(status != NC_NOERR)
  1712. return status;
  1713. if(NC_indef(inncp))
  1714. {
  1715. return NC_EINDEFINE;
  1716. }
  1717. status = NC_check_id(ncid_out, &outncp);
  1718. if(status != NC_NOERR)
  1719. return status;
  1720. if(NC_readonly(outncp))
  1721. {
  1722. /* output file isn't writable */
  1723. return NC_EPERM;
  1724. }
  1725. if(NC_indef(outncp))
  1726. {
  1727. return NC_EINDEFINE;
  1728. }
  1729. /* find the variable in the input cdf */
  1730. invp = NC_lookupvar(inncp, varid);
  1731. if(invp == NULL)
  1732. {
  1733. return NC_ENOTVAR;
  1734. }
  1735. /* find the variable in the output cdf */
  1736. if(NC_findvar(&outncp->vars, invp->name->cp, &outvp) == -1)
  1737. {
  1738. return NC_ENOTVAR;
  1739. }
  1740. /* can we even attempt to copy without conversion? */
  1741. if(outvp->type != invp->type)
  1742. {
  1743. return NC_EINVAL;
  1744. }
  1745. if( (invp->ndims == 0 && outvp->ndims != 0)
  1746. || (invp->ndims != 0 && outvp->ndims == 0)
  1747. || (IS_RECVAR(invp) && !IS_RECVAR(outvp))
  1748. || (!IS_RECVAR(invp) && IS_RECVAR(outvp))
  1749. || (invp->len != outvp->len)
  1750. )
  1751. {
  1752. return NC_EINVAL;
  1753. }
  1754. /*
  1755. * Check coordinates
  1756. */
  1757. {
  1758. ALLOC_ONSTACK(coord, size_t, invp->ndims);
  1759. const size_t nrecs = NC_get_numrecs(inncp);
  1760. (void) memcpy(coord, invp->shape, invp->ndims * sizeof(size_t));
  1761. if(IS_RECVAR(invp))
  1762. *coord = nrecs;
  1763. {
  1764. size_t ii = 0;
  1765. for(; ii < invp->ndims; ii++)
  1766. coord[ii] --;
  1767. }
  1768. /* at this point, coord is the largest valid coord of invp */
  1769. if(NCcoordck(outncp, outvp, coord) != NC_NOERR)
  1770. {
  1771. return NC_EINVAL;
  1772. }
  1773. /* else */
  1774. (void) memset(coord, 0, invp->ndims * sizeof(size_t));
  1775. if(!IS_RECVAR(invp))
  1776. {
  1777. status = NCxvarcpy(inncp, invp, coord,
  1778. outncp, outvp, coord,
  1779. invp->len);
  1780. goto done;
  1781. }
  1782. /* else */
  1783. status = NCvnrecs(outncp, nrecs);
  1784. if(status != NC_NOERR)
  1785. goto done;
  1786. for( /*NADA*/; *coord < nrecs; (*coord)++)
  1787. {
  1788. status = NCxvarcpy(inncp, invp, coord,
  1789. outncp, outvp, coord,
  1790. invp->len);
  1791. if(status != NC_NOERR)
  1792. break;
  1793. }
  1794. done:
  1795. FREE_ONSTACK(coord);
  1796. }
  1797. return status;
  1798. }
  1799. /* no longer deprecated, used to support the 2.x interface and also the netcdf-4 api. */
  1800. int
  1801. nc_get_att(int ncid, int varid, const char *name, void *value)
  1802. {
  1803. int status;
  1804. nc_type atttype;
  1805. status = nc_inq_atttype(ncid, varid, name, &atttype);
  1806. if(status != NC_NOERR)
  1807. return status;
  1808. switch (atttype) {
  1809. case NC_BYTE:
  1810. return nc_get_att_schar(ncid, varid, name,
  1811. (schar *)value);
  1812. case NC_CHAR:
  1813. return nc_get_att_text(ncid, varid, name,
  1814. (char *)value);
  1815. case NC_SHORT:
  1816. return nc_get_att_short(ncid, varid, name,
  1817. (short *)value);
  1818. case NC_INT:
  1819. #if (SIZEOF_INT >= X_SIZEOF_INT)
  1820. return nc_get_att_int(ncid, varid, name,
  1821. (int *)value);
  1822. #elif SIZEOF_LONG == X_SIZEOF_INT
  1823. return nc_get_att_long(ncid, varid, name,
  1824. (long *)value);
  1825. #endif
  1826. case NC_FLOAT:
  1827. return nc_get_att_float(ncid, varid, name,
  1828. (float *)value);
  1829. case NC_DOUBLE:
  1830. return nc_get_att_double(ncid, varid, name,
  1831. (double *)value);
  1832. }
  1833. return NC_EBADTYPE;
  1834. }
  1835. int
  1836. nc_put_att(
  1837. int ncid,
  1838. int varid,
  1839. const char *name,
  1840. nc_type type,
  1841. size_t nelems,
  1842. const void *value)
  1843. {
  1844. switch (type) {
  1845. case NC_BYTE:
  1846. return nc_put_att_schar(ncid, varid, name, type, nelems,
  1847. (schar *)value);
  1848. case NC_CHAR:
  1849. return nc_put_att_text(ncid, varid, name, nelems,
  1850. (char *)value);
  1851. case NC_SHORT:
  1852. return nc_put_att_short(ncid, varid, name, type, nelems,
  1853. (short *)value);
  1854. case NC_INT:
  1855. #if (SIZEOF_INT >= X_SIZEOF_INT)
  1856. return nc_put_att_int(ncid, varid, name, type, nelems,
  1857. (int *)value);
  1858. #elif SIZEOF_LONG == X_SIZEOF_INT
  1859. return nc_put_att_long(ncid, varid, name, type, nelems,
  1860. (long *)value);
  1861. #endif
  1862. case NC_FLOAT:
  1863. return nc_put_att_float(ncid, varid, name, type, nelems,
  1864. (float *)value);
  1865. case NC_DOUBLE:
  1866. return nc_put_att_double(ncid, varid, name, type, nelems,
  1867. (double *)value);
  1868. }
  1869. return NC_EBADTYPE;
  1870. }
  1871. int
  1872. nc_get_var1(int ncid, int varid, const size_t *coord, void *value)
  1873. {
  1874. int status;
  1875. nc_type vartype;
  1876. status = nc_inq_vartype(ncid, varid, &vartype);
  1877. if(status != NC_NOERR)
  1878. return status;
  1879. switch(vartype){
  1880. case NC_CHAR:
  1881. return nc_get_var1_text(ncid, varid, coord,
  1882. (char *) value);
  1883. case NC_BYTE:
  1884. return nc_get_var1_schar(ncid, varid, coord,
  1885. (schar *) value);
  1886. case NC_SHORT:
  1887. return nc_get_var1_short(ncid, varid, coord,
  1888. (short *) value);
  1889. case NC_INT:
  1890. return nc_get_var1_int(ncid, varid, coord,
  1891. (int *) value);
  1892. case NC_FLOAT:
  1893. return nc_get_var1_float(ncid, varid, coord,
  1894. (float *) value);
  1895. case NC_DOUBLE:
  1896. return nc_get_var1_double(ncid, varid, coord,
  1897. (double *) value);
  1898. }
  1899. return NC_EBADTYPE;
  1900. }
  1901. int
  1902. nc_put_var1(int ncid, int varid, const size_t *coord, const void *value)
  1903. {
  1904. int status;
  1905. nc_type vartype;
  1906. status = nc_inq_vartype(ncid, varid, &vartype);
  1907. if(status != NC_NOERR)
  1908. return status;
  1909. switch(vartype){
  1910. case NC_CHAR:
  1911. return nc_put_var1_text(ncid, varid, coord,
  1912. (const char *) value);
  1913. case NC_BYTE:
  1914. return nc_put_var1_schar(ncid, varid, coord,
  1915. (const schar *) value);
  1916. case NC_SHORT:
  1917. return nc_put_var1_short(ncid, varid, coord,
  1918. (const short *) value);
  1919. case NC_INT:
  1920. return nc_put_var1_int(ncid, varid, coord,
  1921. (const int *) value);
  1922. case NC_FLOAT:
  1923. return nc_put_var1_float(ncid, varid, coord,
  1924. (const float *) value);
  1925. case NC_DOUBLE:
  1926. return nc_put_var1_double(ncid, varid, coord,
  1927. (const double *) value);
  1928. }
  1929. return NC_EBADTYPE;
  1930. }
  1931. int
  1932. nc_get_vara(int ncid, int varid,
  1933. const size_t *start, const size_t *edges, void *value)
  1934. {
  1935. int status;
  1936. nc_type vartype;
  1937. status = nc_inq_vartype(ncid, varid, &vartype);
  1938. if(status != NC_NOERR)
  1939. return status;
  1940. switch(vartype){
  1941. case NC_CHAR:
  1942. return nc_get_vara_text(ncid, varid, start, edges,
  1943. (char *) value);
  1944. case NC_BYTE:
  1945. return nc_get_vara_schar(ncid, varid, start, edges,
  1946. (schar *) value);
  1947. case NC_SHORT:
  1948. return nc_get_vara_short(ncid, varid, start, edges,
  1949. (short *) value);
  1950. case NC_INT:
  1951. #if (SIZEOF_INT >= X_SIZEOF_INT)
  1952. return nc_get_vara_int(ncid, varid, start, edges,
  1953. (int *) value);
  1954. #elif SIZEOF_LONG == X_SIZEOF_INT
  1955. return nc_get_vara_long(ncid, varid, start, edges,
  1956. (long *) value);
  1957. #else
  1958. #error "nc_get_vara implementation"
  1959. #endif
  1960. case NC_FLOAT:
  1961. return nc_get_vara_float(ncid, varid, start, edges,
  1962. (float *) value);
  1963. case NC_DOUBLE:
  1964. return nc_get_vara_double(ncid, varid, start, edges,
  1965. (double *) value);
  1966. }
  1967. return NC_EBADTYPE;
  1968. }
  1969. int
  1970. nc_put_vara(int ncid, int varid,
  1971. const size_t *start, const size_t *edges, const void *value)
  1972. {
  1973. int status;
  1974. nc_type vartype;
  1975. status = nc_inq_vartype(ncid, varid, &vartype);
  1976. if(status != NC_NOERR)
  1977. return status;
  1978. switch(vartype){
  1979. case NC_CHAR:
  1980. return nc_put_vara_text(ncid, varid, start, edges,
  1981. (const char *) value);
  1982. case NC_BYTE:
  1983. return nc_put_vara_schar(ncid, varid, start, edges,
  1984. (const schar *) value);
  1985. case NC_SHORT:
  1986. return nc_put_vara_short(ncid, varid, start, edges,
  1987. (const short *) value);
  1988. case NC_INT:
  1989. return nc_put_vara_int(ncid, varid, start, edges,
  1990. (const int *) value);
  1991. case NC_FLOAT:
  1992. return nc_put_vara_float(ncid, varid, start, edges,
  1993. (const float *) value);
  1994. case NC_DOUBLE:
  1995. return nc_put_vara_double(ncid, varid, start, edges,
  1996. (const double *) value);
  1997. }
  1998. return NC_EBADTYPE;
  1999. }
  2000. int
  2001. nc_get_varm (
  2002. int ncid,
  2003. int varid,
  2004. const size_t * start,
  2005. const size_t * edges,
  2006. const ptrdiff_t * stride,
  2007. const ptrdiff_t * map,
  2008. void *value)
  2009. {
  2010. int status;
  2011. nc_type vartype;
  2012. int varndims;
  2013. ptrdiff_t *cvtmap = NULL;
  2014. status = nc_inq_vartype(ncid, varid, &vartype);
  2015. if(status != NC_NOERR)
  2016. return status;
  2017. status = nc_inq_varndims(ncid, varid, &varndims);
  2018. if(status != NC_NOERR)
  2019. return status;
  2020. if(map != NULL && varndims != 0)
  2021. {
  2022. /*
  2023. * convert map units from bytes to units of sizeof(type)
  2024. */
  2025. size_t ii;
  2026. const ptrdiff_t szof = (ptrdiff_t) nctypelen(vartype);
  2027. cvtmap = (ptrdiff_t *)calloc(varndims, sizeof(ptrdiff_t));
  2028. if(cvtmap == NULL)
  2029. return NC_ENOMEM;
  2030. for(ii = 0; ii < varndims; ii++)
  2031. {
  2032. if(map[ii] % szof != 0)
  2033. {
  2034. free(cvtmap);
  2035. return NC_EINVAL;
  2036. }
  2037. cvtmap[ii] = map[ii] / szof;
  2038. }
  2039. map = cvtmap;
  2040. }
  2041. switch(vartype){
  2042. case NC_CHAR:
  2043. status = nc_get_varm_text(ncid, varid, start, edges,
  2044. stride, map,
  2045. (char *) value);
  2046. break;
  2047. case NC_BYTE:
  2048. status = nc_get_varm_schar(ncid, varid, start, edges,
  2049. stride, map,
  2050. (schar *) value);
  2051. break;
  2052. case NC_SHORT:
  2053. status = nc_get_varm_short(ncid, varid, start, edges,
  2054. stride, map,
  2055. (short *) value);
  2056. break;
  2057. case NC_INT:
  2058. #if (SIZEOF_INT >= X_SIZEOF_INT)
  2059. status = nc_get_varm_int(ncid, varid, start, edges,
  2060. stride, map,
  2061. (int *) value);
  2062. #elif SIZEOF_LONG == X_SIZEOF_INT
  2063. status = nc_get_varm_long(ncid, varid, start, edges,
  2064. stride, map,
  2065. (long *) value);
  2066. #else
  2067. #error "nc_get_varm implementation"
  2068. #endif
  2069. break;
  2070. case NC_FLOAT:
  2071. status = nc_get_varm_float(ncid, varid, start, edges,
  2072. stride, map,
  2073. (float *) value);
  2074. break;
  2075. case NC_DOUBLE:
  2076. status = nc_get_varm_double(ncid, varid, start, edges,
  2077. stride, map,
  2078. (double *) value);
  2079. break;
  2080. default:
  2081. status = NC_EBADTYPE;
  2082. break;
  2083. }
  2084. if(cvtmap != NULL)
  2085. {
  2086. free(cvtmap);
  2087. }
  2088. return status;
  2089. }
  2090. int
  2091. nc_put_varm (
  2092. int ncid,
  2093. int varid,
  2094. const size_t * start,
  2095. const size_t * edges,
  2096. const ptrdiff_t * stride,
  2097. const ptrdiff_t * map,
  2098. const void *value)
  2099. {
  2100. int status;
  2101. nc_type vartype;
  2102. int varndims;
  2103. ptrdiff_t *cvtmap = NULL;
  2104. status = nc_inq_vartype(ncid, varid, &vartype);
  2105. if(status != NC_NOERR)
  2106. return status;
  2107. status = nc_inq_varndims(ncid, varid, &varndims);
  2108. if(status != NC_NOERR)
  2109. return status;
  2110. if(map != NULL && varndims != 0)
  2111. {
  2112. /*
  2113. * convert map units from bytes to units of sizeof(type)
  2114. */
  2115. size_t ii;
  2116. const ptrdiff_t szof = (ptrdiff_t) nctypelen(vartype);
  2117. cvtmap = (ptrdiff_t *)calloc(varndims, sizeof(ptrdiff_t));
  2118. if(cvtmap == NULL)
  2119. return NC_ENOMEM;
  2120. for(ii = 0; ii < varndims; ii++)
  2121. {
  2122. if(map[ii] % szof != 0)
  2123. {
  2124. free(cvtmap);
  2125. return NC_EINVAL;
  2126. }
  2127. cvtmap[ii] = map[ii] / szof;
  2128. }
  2129. map = cvtmap;
  2130. }
  2131. switch(vartype){
  2132. case NC_CHAR:
  2133. status = nc_put_varm_text(ncid, varid, start, edges,
  2134. stride, map,
  2135. (const char *) value);
  2136. break;
  2137. case NC_BYTE:
  2138. status = nc_put_varm_schar(ncid, varid, start, edges,
  2139. stride, map,
  2140. (const schar *) value);
  2141. break;
  2142. case NC_SHORT:
  2143. status = nc_put_varm_short(ncid, varid, start, edges,
  2144. stride, map,
  2145. (const short *) value);
  2146. break;
  2147. case NC_INT:
  2148. #if (SIZEOF_INT >= X_SIZEOF_INT)
  2149. status = nc_put_varm_int(ncid, varid, start, edges,
  2150. stride, map,
  2151. (const int *) value);
  2152. #elif SIZEOF_LONG == X_SIZEOF_INT
  2153. status = nc_put_varm_long(ncid, varid, start, edges,
  2154. stride, map,
  2155. (const long *) value);
  2156. #else
  2157. #error "nc_put_varm implementation"
  2158. #endif
  2159. break;
  2160. case NC_FLOAT:
  2161. status = nc_put_varm_float(ncid, varid, start, edges,
  2162. stride, map,
  2163. (const f…

Large files files are truncated, but you can click here to view the full file