PageRenderTime 63ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/other/netcdf_write_matrix/src/ncdump/vardata.c

http://github.com/jbeezley/wrf-fire
C | 1287 lines | 1181 code | 36 blank | 70 comment | 79 complexity | 98740fec7982f869b9bd74906f0aa679 MD5 | raw file
Possible License(s): AGPL-1.0
  1. /*********************************************************************
  2. * Copyright 1993, UCAR/Unidata
  3. * See netcdf/COPYRIGHT file for copying and redistribution conditions.
  4. * $Header: /upc/share/CVS/netcdf-3/ncdump/vardata.c,v 1.12 2005/07/22 23:01:39 russ Exp $
  5. *********************************************************************/
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #ifndef NO_FLOAT_H
  11. #include <float.h> /* for FLT_EPSILON, DBL_EPSILON */
  12. #endif /* NO_FLOAT_H */
  13. #include <netcdf.h>
  14. #include "ncdump.h"
  15. #include "dumplib.h"
  16. #include "vardata.h"
  17. static float float_epsilon(void);
  18. static double double_epsilon(void);
  19. static void init_epsilons(void);
  20. static void printbval(char* sout, const char* fmt, const ncvar_t* varp,
  21. signed char val);
  22. static void printsval(char* sout, const char* fmt, const ncvar_t* varp,
  23. short val);
  24. static void printival(char* sout, const char* fmt, const ncvar_t* varp,
  25. int val);
  26. static void printfval(char* sout, const char* fmt, const ncvar_t* varp,
  27. float val);
  28. static void printdval(char* sout, const char* fmt, const ncvar_t* varp,
  29. double val);
  30. static void lastdelim(boolean more, boolean lastrow);
  31. static void annotate(const ncvar_t* vp, const fspec_t* fsp,
  32. const size_t* cor, long iel);
  33. static void pr_tvals(const ncvar_t *vp, size_t len, const char *fmt,
  34. boolean more, boolean lastrow, const char *vals,
  35. const fspec_t* fsp, const size_t *cor);
  36. static void pr_bvals(const ncvar_t *vp, size_t len, const char *fmt,
  37. boolean more, boolean lastrow, const signed char *vals,
  38. const fspec_t* fsp, const size_t *cor);
  39. static void pr_svals(const ncvar_t *vp, size_t len, const char *fmt,
  40. boolean more, boolean lastrow, const short *vals,
  41. const fspec_t* fsp, const size_t *cor);
  42. static void pr_ivals(const ncvar_t *vp, size_t len, const char *fmt,
  43. boolean more, boolean lastrow, const int *vals,
  44. const fspec_t* fsp, const size_t *cor);
  45. static void pr_fvals(const ncvar_t *vp, size_t len, const char *fmt,
  46. boolean more, boolean lastrow, const float *vals,
  47. const fspec_t* fsp, const size_t *cor);
  48. static void pr_dvals(const ncvar_t *vp, size_t len, const char *fmt,
  49. boolean more, boolean lastrow, const double *vals,
  50. const fspec_t* fsp, const size_t *cor);
  51. static int upcorner(const size_t* dims, int ndims, size_t* odom,
  52. const size_t* add);
  53. static void lastdelim2 (boolean more, boolean lastrow);
  54. #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
  55. static float float_eps;
  56. static double double_eps;
  57. static float
  58. float_epsilon(void)
  59. {
  60. float float_eps;
  61. #ifndef NO_FLOAT_H
  62. float_eps = FLT_EPSILON;
  63. #else /* NO_FLOAT_H */
  64. {
  65. float etop, ebot, eps;
  66. float one = 1.0;
  67. float two = 2.0;
  68. etop = 1.0;
  69. ebot = 0.0;
  70. eps = ebot + (etop - ebot)/two;
  71. while (eps != ebot && eps != etop) {
  72. float epsp1;
  73. epsp1 = one + eps;
  74. if (epsp1 > one)
  75. etop = eps;
  76. else
  77. ebot = eps;
  78. eps = ebot + (etop - ebot)/two;
  79. }
  80. float_eps = two * etop;
  81. }
  82. #endif /* NO_FLOAT_H */
  83. return float_eps;
  84. }
  85. static double
  86. double_epsilon(void)
  87. {
  88. double double_eps;
  89. #ifndef NO_FLOAT_H
  90. double_eps = DBL_EPSILON;
  91. #else /* NO_FLOAT_H */
  92. {
  93. double etop, ebot, eps;
  94. double one = 1.0;
  95. double two = 2.0;
  96. etop = 1.0;
  97. ebot = 0.0;
  98. eps = ebot + (etop - ebot)/two;
  99. while (eps != ebot && eps != etop) {
  100. double epsp1;
  101. epsp1 = one + eps;
  102. if (epsp1 > one)
  103. etop = eps;
  104. else
  105. ebot = eps;
  106. eps = ebot + (etop - ebot)/two;
  107. }
  108. double_eps = two * etop;
  109. }
  110. #endif /* NO_FLOAT_H */
  111. return double_eps;
  112. }
  113. static void
  114. init_epsilons(void)
  115. {
  116. float_eps = float_epsilon();
  117. double_eps = double_epsilon();
  118. }
  119. /*
  120. * Output a value of a byte variable, except if there is a fill value for
  121. * the variable and the value is the fill value, print the fill-value string
  122. * instead.
  123. */
  124. static void
  125. printbval(
  126. char *sout, /* string where output goes */
  127. const char *fmt, /* printf format used for value */
  128. const ncvar_t *varp, /* variable */
  129. signed char val /* value */
  130. )
  131. {
  132. if (varp->has_fillval) {
  133. double fillval = varp->fillval;
  134. if(fillval == val) {
  135. (void) sprintf(sout, FILL_STRING);
  136. return;
  137. }
  138. }
  139. (void) sprintf(sout, fmt, val);
  140. }
  141. /*
  142. * Output a value of a short variable, except if there is a fill value for
  143. * the variable and the value is the fill value, print the fill-value string
  144. * instead.
  145. */
  146. static void
  147. printsval(
  148. char *sout, /* string where output goes */
  149. const char *fmt, /* printf format used for value */
  150. const ncvar_t *varp, /* variable */
  151. short val /* value */
  152. )
  153. {
  154. if (varp->has_fillval) {
  155. double fillval = varp->fillval;
  156. if(fillval == val) {
  157. (void) sprintf(sout, FILL_STRING);
  158. return;
  159. }
  160. }
  161. (void) sprintf(sout, fmt, val);
  162. }
  163. /*
  164. * Output a value of an int variable, except if there is a fill value for
  165. * the variable and the value is the fill value, print the fill-value string
  166. * instead.
  167. */
  168. static void
  169. printival(
  170. char *sout, /* string where output goes */
  171. const char *fmt, /* printf format used for value */
  172. const ncvar_t *varp, /* variable */
  173. int val /* value */
  174. )
  175. {
  176. if (varp->has_fillval) {
  177. int fillval = (int)varp->fillval;
  178. if(fillval == val) {
  179. (void) sprintf(sout, FILL_STRING);
  180. return;
  181. }
  182. }
  183. (void) sprintf(sout, fmt, val);
  184. }
  185. #define absval(x) ( (x) < 0 ? -(x) : (x) )
  186. /*
  187. * Output a value of a float variable, except if there is a fill value for
  188. * the variable and the value is the fill value, print the fill-value string
  189. * instead. Floating-point fill values need only be within machine epsilon of
  190. * defined fill value.
  191. */
  192. static void
  193. printfval(
  194. char *sout, /* string where output goes */
  195. const char *fmt, /* printf format used for value */
  196. const ncvar_t *varp, /* variable */
  197. float val /* value */
  198. )
  199. {
  200. if(varp->has_fillval) {
  201. double fillval = varp->fillval;
  202. if((val > 0) == (fillval > 0) && /* prevents potential overflow */
  203. (absval(val - fillval) <= absval(float_eps * fillval))) {
  204. (void) sprintf(sout, FILL_STRING);
  205. return;
  206. }
  207. }
  208. (void) sprintf(sout, fmt, val);
  209. }
  210. /*
  211. * Output a value of a double variable, except if there is a fill value for
  212. * the variable and the value is the fill value, print the fill-value string
  213. * instead. Floating-point fill values need only be within machine epsilon of
  214. * defined fill value.
  215. */
  216. static void
  217. printdval(
  218. char *sout, /* string where output goes */
  219. const char *fmt, /* printf format used for value */
  220. const ncvar_t *varp, /* variable */
  221. double val /* value */
  222. )
  223. {
  224. if(varp->has_fillval) {
  225. double fillval = varp->fillval;
  226. if((val > 0) == (fillval > 0) && /* prevents potential overflow */
  227. (absval(val - fillval) <= absval(double_eps * fillval))) {
  228. (void) sprintf(sout, FILL_STRING);
  229. return;
  230. }
  231. }
  232. (void) sprintf(sout, fmt, val);
  233. }
  234. /*
  235. * print last delimiter in each line before annotation (, or ;)
  236. */
  237. static void
  238. lastdelim (boolean more, boolean lastrow)
  239. {
  240. if (more) {
  241. Printf(", ");
  242. } else {
  243. if(lastrow) {
  244. Printf(";");
  245. } else {
  246. Printf(",");
  247. }
  248. }
  249. }
  250. /*
  251. * print last delimiter in each line before annotation (, or ;)
  252. */
  253. static void
  254. lastdelim2 (boolean more, boolean lastrow)
  255. {
  256. if (more) {
  257. lput(", ");
  258. } else {
  259. if(lastrow) {
  260. lput(" ;");
  261. lput("\n");
  262. } else {
  263. lput(",\n");
  264. lput(" ");
  265. }
  266. }
  267. }
  268. /*
  269. * Annotates a value in data section with var name and indices in comment
  270. */
  271. static void
  272. annotate(
  273. const ncvar_t *vp, /* variable */
  274. const fspec_t* fsp, /* formatting specs */
  275. const size_t *cor, /* corner coordinates */
  276. long iel /* which element in current row */
  277. )
  278. {
  279. int vrank = vp->ndims;
  280. int id;
  281. /* print indices according to data_lang */
  282. (void) printf(" // %s(", vp->name);
  283. switch (fsp->data_lang) {
  284. case LANG_C:
  285. /* C variable indices */
  286. for (id = 0; id < vrank-1; id++)
  287. Printf("%lu,", (unsigned long) cor[id]);
  288. Printf("%lu", (unsigned long) cor[id] + iel);
  289. break;
  290. case LANG_F:
  291. /* Fortran variable indices */
  292. Printf("%lu", (unsigned long) cor[vrank-1] + iel + 1);
  293. for (id = vrank-2; id >=0 ; id--) {
  294. Printf(",%lu", 1 + (unsigned long) cor[id]);
  295. }
  296. break;
  297. }
  298. Printf(")\n ");
  299. }
  300. /*
  301. * Print a number of char variable values, where the optional comments
  302. * for each value identify the variable, and each dimension index.
  303. */
  304. static void
  305. pr_tvals(
  306. const ncvar_t *vp, /* variable */
  307. size_t len, /* number of values to print */
  308. const char *fmt, /* printf format used for each value. If
  309. * nc_type is NC_CHAR and this is NULL,
  310. * character arrays will be printed as
  311. * strings enclosed in quotes. */
  312. boolean more, /* true if more data for this row will
  313. * follow, so add trailing comma */
  314. boolean lastrow, /* true if this is the last row for this
  315. * variable, so terminate with ";" instead
  316. * of "," */
  317. const char *vals, /* pointer to block of values */
  318. const fspec_t* fsp, /* formatting specs */
  319. const size_t *cor /* corner coordinates */
  320. )
  321. {
  322. long iel;
  323. const char *sp;
  324. unsigned char uc;
  325. char sout[100]; /* temporary string for each encoded output */
  326. if (fmt == 0 || STREQ(fmt,"%s") || STREQ(fmt,"")) { /* as string */
  327. Printf("\"");
  328. /* adjust len so trailing nulls don't get printed */
  329. sp = vals + len;
  330. while (len != 0 && *--sp == '\0')
  331. len--;
  332. for (iel = 0; iel < len; iel++)
  333. switch (uc = *vals++ & 0377) {
  334. case '\b':
  335. Printf("\\b");
  336. break;
  337. case '\f':
  338. Printf("\\f");
  339. break;
  340. case '\n': /* generate linebreaks after new-lines */
  341. Printf("\\n\",\n \"");
  342. break;
  343. case '\r':
  344. Printf("\\r");
  345. break;
  346. case '\t':
  347. Printf("\\t");
  348. break;
  349. case '\v':
  350. Printf("\\v");
  351. break;
  352. case '\\':
  353. Printf("\\\\");
  354. break;
  355. case '\'':
  356. Printf("\\\'");
  357. break;
  358. case '\"':
  359. Printf("\\\"");
  360. break;
  361. default:
  362. if (isprint(uc))
  363. Printf("%c",uc);
  364. else
  365. Printf("\\%.3o",uc);
  366. break;
  367. }
  368. Printf("\"");
  369. if (fsp->full_data_cmnts) {
  370. lastdelim (more, lastrow);
  371. annotate (vp, fsp, (size_t *)cor, 0L);
  372. }
  373. } else { /* use format from C_format attribute */
  374. for (iel = 0; iel < len-1; iel++) {
  375. if (fsp->full_data_cmnts) {
  376. Printf(fmt, *vals++);
  377. Printf(", ");
  378. annotate (vp, fsp, (size_t *)cor, iel);
  379. } else {
  380. (void) sprintf(sout, fmt, *vals++);
  381. (void) strcat(sout, ", ");
  382. lput(sout);
  383. }
  384. }
  385. if (fsp->full_data_cmnts) {
  386. Printf(fmt, *vals++);
  387. lastdelim (more, lastrow);
  388. annotate (vp, fsp, (size_t *)cor, iel);
  389. } else {
  390. (void) sprintf(sout, fmt, *vals++);
  391. lput(sout);
  392. }
  393. }
  394. if (!fsp->full_data_cmnts) {
  395. lastdelim2 (more, lastrow);
  396. }
  397. }
  398. /*
  399. * Print a number of byte variable values, where the optional comments
  400. * for each value identify the variable, and each dimension index.
  401. */
  402. static void
  403. pr_bvals(
  404. const ncvar_t *vp, /* variable */
  405. size_t len, /* number of values to print */
  406. const char *fmt, /* printf format used for each value. If
  407. * nc_type is NC_CHAR and this is NULL,
  408. * character arrays will be printed as
  409. * strings enclosed in quotes. */
  410. boolean more, /* true if more data for this row will
  411. * follow, so add trailing comma */
  412. boolean lastrow, /* true if this is the last row for this
  413. * variable, so terminate with ";" instead
  414. * of "," */
  415. const signed char *vals, /* pointer to block of values */
  416. const fspec_t* fsp, /* formatting specs */
  417. const size_t *cor /* corner coordinates */
  418. )
  419. {
  420. long iel;
  421. char sout[100]; /* temporary string for each encoded output */
  422. for (iel = 0; iel < len-1; iel++) {
  423. printbval(sout, fmt, vp, *vals++);
  424. if (fsp->full_data_cmnts) {
  425. Printf(sout);
  426. Printf(",");
  427. annotate (vp, fsp, cor, iel);
  428. } else {
  429. (void) strcat(sout, ", ");
  430. lput(sout);
  431. }
  432. }
  433. printbval(sout, fmt, vp, *vals++);
  434. if (fsp->full_data_cmnts) {
  435. Printf(sout);
  436. lastdelim (more, lastrow);
  437. annotate (vp, fsp, cor, iel);
  438. } else {
  439. lput(sout);
  440. lastdelim2 (more, lastrow);
  441. }
  442. }
  443. /*
  444. * Print a number of short variable values, where the optional comments
  445. * for each value identify the variable, and each dimension index.
  446. */
  447. static void
  448. pr_svals(
  449. const ncvar_t *vp, /* variable */
  450. size_t len, /* number of values to print */
  451. const char *fmt, /* printf format used for each value. If
  452. * nc_type is NC_CHAR and this is NULL,
  453. * character arrays will be printed as
  454. * strings enclosed in quotes. */
  455. boolean more, /* true if more data for this row will
  456. * follow, so add trailing comma */
  457. boolean lastrow, /* true if this is the last row for this
  458. * variable, so terminate with ";" instead
  459. * of "," */
  460. const short *vals, /* pointer to block of values */
  461. const fspec_t* fsp, /* formatting specs */
  462. const size_t *cor /* corner coordinates */
  463. )
  464. {
  465. long iel;
  466. char sout[100]; /* temporary string for each encoded output */
  467. for (iel = 0; iel < len-1; iel++) {
  468. printsval(sout, fmt, vp, *vals++);
  469. if (fsp->full_data_cmnts) {
  470. Printf(sout);
  471. Printf(",");
  472. annotate (vp, fsp, cor, iel);
  473. } else {
  474. (void) strcat(sout, ", ");
  475. lput(sout);
  476. }
  477. }
  478. printsval(sout, fmt, vp, *vals++);
  479. if (fsp->full_data_cmnts) {
  480. Printf(sout);
  481. lastdelim (more, lastrow);
  482. annotate (vp, fsp, cor, iel);
  483. } else {
  484. lput(sout);
  485. lastdelim2 (more, lastrow);
  486. }
  487. }
  488. /*
  489. * Print a number of int variable values, where the optional comments
  490. * for each value identify the variable, and each dimension index.
  491. */
  492. static void
  493. pr_ivals(
  494. const ncvar_t *vp, /* variable */
  495. size_t len, /* number of values to print */
  496. const char *fmt, /* printf format used for each value. If
  497. * nc_type is NC_CHAR and this is NULL,
  498. * character arrays will be printed as
  499. * strings enclosed in quotes. */
  500. boolean more, /* true if more data for this row will
  501. * follow, so add trailing comma */
  502. boolean lastrow, /* true if this is the last row for this
  503. * variable, so terminate with ";" instead
  504. * of "," */
  505. const int *vals, /* pointer to block of values */
  506. const fspec_t* fsp, /* formatting specs */
  507. const size_t *cor /* corner coordinates */
  508. )
  509. {
  510. long iel;
  511. char sout[100]; /* temporary string for each encoded output */
  512. for (iel = 0; iel < len-1; iel++) {
  513. printival(sout, fmt, vp, *vals++);
  514. if (fsp->full_data_cmnts) {
  515. Printf(sout);
  516. Printf(",");
  517. annotate (vp, fsp, cor, iel);
  518. } else {
  519. (void) strcat(sout, ", ");
  520. lput(sout);
  521. }
  522. }
  523. printival(sout, fmt, vp, *vals++);
  524. if (fsp->full_data_cmnts) {
  525. Printf(sout);
  526. lastdelim (more, lastrow);
  527. annotate (vp, fsp, cor, iel);
  528. } else {
  529. lput(sout);
  530. lastdelim2 (more, lastrow);
  531. }
  532. }
  533. /*
  534. * Print a number of float variable values, where the optional comments
  535. * for each value identify the variable, and each dimension index.
  536. */
  537. static void
  538. pr_fvals(
  539. const ncvar_t *vp, /* variable */
  540. size_t len, /* number of values to print */
  541. const char *fmt, /* printf format used for each value. If
  542. * nc_type is NC_CHAR and this is NULL,
  543. * character arrays will be printed as
  544. * strings enclosed in quotes. */
  545. boolean more, /* true if more data for this row will
  546. * follow, so add trailing comma */
  547. boolean lastrow, /* true if this is the last row for this
  548. * variable, so terminate with ";" instead
  549. * of "," */
  550. const float *vals, /* pointer to block of values */
  551. const fspec_t* fsp, /* formatting specs */
  552. const size_t *cor /* corner coordinates */
  553. )
  554. {
  555. long iel;
  556. char sout[100]; /* temporary string for each encoded output */
  557. for (iel = 0; iel < len-1; iel++) {
  558. printfval(sout, fmt, vp, *vals++);
  559. if (fsp->full_data_cmnts) {
  560. Printf(sout);
  561. Printf(",");
  562. annotate (vp, fsp, cor, iel);
  563. } else {
  564. (void) strcat(sout, ", ");
  565. lput(sout);
  566. }
  567. }
  568. printfval(sout, fmt, vp, *vals++);
  569. if (fsp->full_data_cmnts) {
  570. Printf(sout);
  571. lastdelim (more, lastrow);
  572. annotate (vp, fsp, cor, iel);
  573. } else {
  574. lput(sout);
  575. lastdelim2 (more, lastrow);
  576. }
  577. }
  578. /*
  579. * Print a number of double variable values, where the optional comments
  580. * for each value identify the variable, and each dimension index.
  581. */
  582. static void
  583. pr_dvals(
  584. const ncvar_t *vp, /* variable */
  585. size_t len, /* number of values to print */
  586. const char *fmt, /* printf format used for each value. If
  587. * nc_type is NC_CHAR and this is NULL,
  588. * character arrays will be printed as
  589. * strings enclosed in quotes. */
  590. boolean more, /* true if more data for this row will
  591. * follow, so add trailing comma */
  592. boolean lastrow, /* true if this is the last row for this
  593. * variable, so terminate with ";" instead
  594. * of "," */
  595. const double *vals, /* pointer to block of values */
  596. const fspec_t* fsp, /* formatting specs */
  597. const size_t *cor /* corner coordinates */
  598. )
  599. {
  600. long iel;
  601. char sout[100]; /* temporary string for each encoded output */
  602. for (iel = 0; iel < len-1; iel++) {
  603. printdval(sout, fmt, vp, *vals++);
  604. if (fsp->full_data_cmnts) {
  605. Printf(sout);
  606. Printf(",");
  607. annotate (vp, fsp, cor, iel);
  608. } else {
  609. (void) strcat(sout, ", ");
  610. lput(sout);
  611. }
  612. }
  613. printdval(sout, fmt, vp, *vals++);
  614. if (fsp->full_data_cmnts) {
  615. Printf(sout);
  616. lastdelim (more, lastrow);
  617. annotate (vp, fsp, cor, iel);
  618. } else {
  619. lput(sout);
  620. lastdelim2 (more, lastrow);
  621. }
  622. }
  623. /*
  624. * Updates a vector of ints, odometer style. Returns 0 if odometer
  625. * overflowed, else 1.
  626. */
  627. static int
  628. upcorner(
  629. const size_t *dims, /* The "odometer" limits for each dimension */
  630. int ndims, /* Number of dimensions */
  631. size_t* odom, /* The "odometer" vector to be updated */
  632. const size_t* add /* A vector to "add" to odom on each update */
  633. )
  634. {
  635. int id;
  636. int ret = 1;
  637. for (id = ndims-1; id > 0; id--) {
  638. odom[id] += add[id];
  639. if(odom[id] >= dims[id]) {
  640. odom[id-1]++;
  641. odom[id] -= dims[id];
  642. }
  643. }
  644. odom[0] += add[0];
  645. if (odom[0] >= dims[0])
  646. ret = 0;
  647. return ret;
  648. }
  649. /* Output the data for a single variable, in CDL syntax. */
  650. int
  651. vardata(
  652. const ncvar_t *vp, /* variable */
  653. size_t vdims[], /* variable dimension sizes */
  654. int ncid, /* netcdf id */
  655. int varid, /* variable id */
  656. const fspec_t* fsp /* formatting specs */
  657. )
  658. {
  659. size_t cor[NC_MAX_DIMS]; /* corner coordinates */
  660. size_t edg[NC_MAX_DIMS]; /* edges of hypercube */
  661. size_t add[NC_MAX_DIMS]; /* "odometer" increment to next "row" */
  662. #define VALBUFSIZ 1000
  663. double vals[VALBUFSIZ] ; /* aligned buffer */
  664. int gulp = VALBUFSIZ;
  665. int id;
  666. int ir;
  667. size_t nels;
  668. size_t ncols;
  669. size_t nrows;
  670. int vrank = vp->ndims;
  671. static int initeps = 0;
  672. /* printf format used to print each value */
  673. const char *fmt = get_fmt(ncid, varid, vp->type);
  674. if (!initeps) { /* make sure epsilons get initialized */
  675. init_epsilons();
  676. initeps = 1;
  677. }
  678. nels = 1;
  679. for (id = 0; id < vrank; id++) {
  680. cor[id] = 0;
  681. edg[id] = 1;
  682. nels *= vdims[id]; /* total number of values for variable */
  683. }
  684. if (vrank <= 1) {
  685. Printf("\n %s = ", vp->name);
  686. set_indent ((int)strlen(vp->name) + 4);
  687. } else {
  688. Printf("\n %s =\n ", vp->name);
  689. set_indent (2);
  690. }
  691. if (vrank < 1) {
  692. ncols = 1;
  693. } else {
  694. ncols = vdims[vrank-1]; /* size of "row" along last dimension */
  695. edg[vrank-1] = vdims[vrank-1];
  696. for (id = 0; id < vrank; id++)
  697. add[id] = 0;
  698. if (vrank > 1)
  699. add[vrank-2] = 1;
  700. }
  701. nrows = nels/ncols; /* number of "rows" */
  702. for (ir = 0; ir < nrows; ir++) {
  703. /*
  704. * rather than just printing a whole row at once (which might exceed
  705. * the capacity of MSDOS platforms, for example), we break each row
  706. * into smaller chunks, if necessary.
  707. */
  708. size_t corsav;
  709. int left = (int)ncols;
  710. boolean lastrow;
  711. if (vrank > 0) {
  712. corsav = cor[vrank-1];
  713. if (fsp->brief_data_cmnts != false
  714. && vrank > 1
  715. && left > 0) { /* print brief comment with indices range */
  716. Printf("// %s(",vp->name);
  717. switch (fsp->data_lang) {
  718. case LANG_C:
  719. /* print brief comment with C variable indices */
  720. for (id = 0; id < vrank-1; id++)
  721. Printf("%lu,", (unsigned long)cor[id]);
  722. if (vdims[vrank-1] == 1)
  723. Printf("0");
  724. else
  725. Printf(" 0-%lu", (unsigned long)vdims[vrank-1]-1);
  726. break;
  727. case LANG_F:
  728. /* print brief comment with Fortran variable indices */
  729. if (vdims[vrank-1] == 1)
  730. Printf("1");
  731. else
  732. Printf("1-%lu ", (unsigned long)vdims[vrank-1]);
  733. for (id = vrank-2; id >=0 ; id--) {
  734. Printf(",%lu", (unsigned long)(1 + cor[id]));
  735. }
  736. break;
  737. }
  738. Printf(")\n ");
  739. set_indent(4);
  740. }
  741. }
  742. lastrow = (boolean)(ir == nrows-1);
  743. while (left > 0) {
  744. size_t toget = left < gulp ? left : gulp;
  745. if (vrank > 0)
  746. edg[vrank-1] = toget;
  747. switch(vp->type) {
  748. case NC_CHAR:
  749. NC_CHECK(
  750. nc_get_vara_text(ncid, varid, cor, edg, (char *)vals) );
  751. pr_tvals(vp, toget, fmt, left > toget, lastrow,
  752. (char *) vals, fsp, cor);
  753. break;
  754. case NC_BYTE:
  755. NC_CHECK(
  756. nc_get_vara_schar(ncid, varid, cor, edg, (signed char *)vals) );
  757. pr_bvals(vp, toget, fmt, left > toget, lastrow,
  758. (signed char *) vals, fsp, cor);
  759. break;
  760. case NC_SHORT:
  761. NC_CHECK(
  762. nc_get_vara_short(ncid, varid, cor, edg, (short *)vals) );
  763. pr_svals(vp, toget, fmt, left > toget, lastrow,
  764. (short *) vals, fsp, cor);
  765. break;
  766. case NC_INT:
  767. NC_CHECK(
  768. nc_get_vara_int(ncid, varid, cor, edg, (int *)vals) );
  769. pr_ivals(vp, toget, fmt, left > toget, lastrow,
  770. (int *) vals, fsp, cor);
  771. break;
  772. case NC_FLOAT:
  773. NC_CHECK(
  774. nc_get_vara_float(ncid, varid, cor, edg, (float *)vals) );
  775. pr_fvals(vp, toget, fmt, left > toget, lastrow,
  776. (float *) vals, fsp, cor);
  777. break;
  778. case NC_DOUBLE:
  779. NC_CHECK(
  780. nc_get_vara_double(ncid, varid, cor, edg, (double *)vals) );
  781. pr_dvals(vp, toget, fmt, left > toget, lastrow,
  782. (double *) vals, fsp, cor);
  783. break;
  784. default:
  785. error("vardata: bad type");
  786. }
  787. left -= toget;
  788. if (vrank > 0)
  789. cor[vrank-1] += toget;
  790. }
  791. if (vrank > 0)
  792. cor[vrank-1] = corsav;
  793. if (ir < nrows-1)
  794. if (!upcorner(vdims,vp->ndims,cor,add))
  795. error("vardata: odometer overflowed!");
  796. set_indent(2);
  797. }
  798. return 0;
  799. }
  800. /*
  801. * print last delimiter in each line before annotation (, or ;)
  802. */
  803. static void
  804. lastdelim2x (boolean more, boolean lastrow)
  805. {
  806. if (more) {
  807. lput(" ");
  808. } else {
  809. if(lastrow) {
  810. lput("\n ");
  811. } else {
  812. lput("\n ");
  813. }
  814. }
  815. }
  816. /*
  817. * Print a number of char variable values.
  818. */
  819. static void
  820. pr_tvalsx(
  821. size_t len, /* number of values to print */
  822. const char *fmt, /* printf format used for each value. If
  823. * nc_type is NC_CHAR and this is NULL,
  824. * character arrays will be printed as
  825. * strings enclosed in quotes. */
  826. boolean more, /* true if more data for this row will
  827. * follow, so add trailing comma */
  828. boolean lastrow, /* true if this is the last row for this
  829. * variable, so terminate with ";" instead
  830. * of "," */
  831. const char *vals, /* pointer to block of values */
  832. const fspec_t *fsp /* formatting specs */
  833. )
  834. {
  835. long iel;
  836. const char *sp;
  837. unsigned char uc;
  838. char sout[100]; /* temporary string for each encoded output */
  839. if (fmt == 0 || STREQ(fmt,"%s") || STREQ(fmt,"")) { /* as string */
  840. Printf("\"");
  841. /* adjust len so trailing nulls don't get printed */
  842. sp = vals + len;
  843. while (len != 0 && *--sp == '\0')
  844. len--;
  845. for (iel = 0; iel < len; iel++)
  846. switch (uc = *vals++ & 0377) {
  847. case '\b':
  848. Printf("\\b");
  849. break;
  850. case '\f':
  851. Printf("\\f");
  852. break;
  853. case '\n': /* generate linebreaks after new-lines */
  854. Printf("\\n\",\n \"");
  855. break;
  856. case '\r':
  857. Printf("\\r");
  858. break;
  859. case '\t':
  860. Printf("\\t");
  861. break;
  862. case '\v':
  863. Printf("\\v");
  864. break;
  865. case '\\':
  866. Printf("\\\\");
  867. break;
  868. case '\'':
  869. Printf("\\\'");
  870. break;
  871. case '\"':
  872. Printf("\\\"");
  873. break;
  874. default:
  875. if (isprint(uc))
  876. Printf("%c",uc);
  877. else
  878. Printf("\\%.3o",uc);
  879. break;
  880. }
  881. Printf("\"");
  882. } else { /* use format from C_format attribute */
  883. for (iel = 0; iel < len-1; iel++) {
  884. (void) sprintf(sout, fmt, *vals++);
  885. (void) strcat(sout, " ");
  886. lput(sout);
  887. }
  888. (void) sprintf(sout, fmt, *vals++);
  889. lput(sout);
  890. }
  891. if (!fsp->full_data_cmnts) {
  892. lastdelim2x (more, lastrow);
  893. }
  894. }
  895. /*
  896. * Print a number of byte variable values.
  897. */
  898. static void
  899. pr_bvalsx(
  900. const ncvar_t *vp, /* variable */
  901. size_t len, /* number of values to print */
  902. const char *fmt, /* printf format used for each value. If
  903. * nc_type is NC_CHAR and this is NULL,
  904. * character arrays will be printed as
  905. * strings enclosed in quotes. */
  906. boolean more, /* true if more data for this row will
  907. * follow, so add trailing comma */
  908. boolean lastrow, /* true if this is the last row for this
  909. * variable, so terminate with ";" instead
  910. * of "," */
  911. const signed char *vals /* pointer to block of values */
  912. )
  913. {
  914. long iel;
  915. char sout[100]; /* temporary string for each encoded output */
  916. for (iel = 0; iel < len-1; iel++) {
  917. printbval(sout, fmt, vp, *vals++);
  918. (void) strcat(sout, " ");
  919. lput(sout);
  920. }
  921. printbval(sout, fmt, vp, *vals++);
  922. lput(sout);
  923. lastdelim2x (more, lastrow);
  924. }
  925. /*
  926. * Print a number of short variable values.
  927. */
  928. static void
  929. pr_svalsx(
  930. const ncvar_t *vp, /* variable */
  931. size_t len, /* number of values to print */
  932. const char *fmt, /* printf format used for each value. If
  933. * nc_type is NC_CHAR and this is NULL,
  934. * character arrays will be printed as
  935. * strings enclosed in quotes. */
  936. boolean more, /* true if more data for this row will
  937. * follow, so add trailing comma */
  938. boolean lastrow, /* true if this is the last row for this
  939. * variable, so terminate with ";" instead
  940. * of "," */
  941. const short *vals /* pointer to block of values */
  942. )
  943. {
  944. long iel;
  945. char sout[100]; /* temporary string for each encoded output */
  946. for (iel = 0; iel < len-1; iel++) {
  947. printsval(sout, fmt, vp, *vals++);
  948. (void) strcat(sout, " ");
  949. lput(sout);
  950. }
  951. printsval(sout, fmt, vp, *vals++);
  952. lput(sout);
  953. lastdelim2x (more, lastrow);
  954. }
  955. /*
  956. * Print a number of int variable values.
  957. */
  958. static void
  959. pr_ivalsx(
  960. const ncvar_t *vp, /* variable */
  961. size_t len, /* number of values to print */
  962. const char *fmt, /* printf format used for each value. If
  963. * nc_type is NC_CHAR and this is NULL,
  964. * character arrays will be printed as
  965. * strings enclosed in quotes. */
  966. boolean more, /* true if more data for this row will
  967. * follow, so add trailing comma */
  968. boolean lastrow, /* true if this is the last row for this
  969. * variable, so terminate with ";" instead
  970. * of "," */
  971. const int *vals /* pointer to block of values */
  972. )
  973. {
  974. long iel;
  975. char sout[100]; /* temporary string for each encoded output */
  976. for (iel = 0; iel < len-1; iel++) {
  977. printival(sout, fmt, vp, *vals++);
  978. (void) strcat(sout, " ");
  979. lput(sout);
  980. }
  981. printival(sout, fmt, vp, *vals++);
  982. lput(sout);
  983. lastdelim2x (more, lastrow);
  984. }
  985. /*
  986. * Print a number of float variable values.
  987. */
  988. static void
  989. pr_fvalsx(
  990. const ncvar_t *vp, /* variable */
  991. size_t len, /* number of values to print */
  992. const char *fmt, /* printf format used for each value. If
  993. * nc_type is NC_CHAR and this is NULL,
  994. * character arrays will be printed as
  995. * strings enclosed in quotes. */
  996. boolean more, /* true if more data for this row will
  997. * follow, so add trailing comma */
  998. boolean lastrow, /* true if this is the last row for this
  999. * variable, so terminate with ";" instead
  1000. * of "," */
  1001. const float *vals /* pointer to block of values */
  1002. )
  1003. {
  1004. long iel;
  1005. char sout[100]; /* temporary string for each encoded output */
  1006. for (iel = 0; iel < len-1; iel++) {
  1007. printfval(sout, fmt, vp, *vals++);
  1008. (void) strcat(sout, " ");
  1009. lput(sout);
  1010. }
  1011. printfval(sout, fmt, vp, *vals++);
  1012. lput(sout);
  1013. lastdelim2x (more, lastrow);
  1014. }
  1015. /*
  1016. * Print a number of double variable values.
  1017. */
  1018. static void
  1019. pr_dvalsx(
  1020. const ncvar_t *vp, /* variable */
  1021. size_t len, /* number of values to print */
  1022. const char *fmt, /* printf format used for each value. If
  1023. * nc_type is NC_CHAR and this is NULL,
  1024. * character arrays will be printed as
  1025. * strings enclosed in quotes. */
  1026. boolean more, /* true if more data for this row will
  1027. * follow, so add trailing comma */
  1028. boolean lastrow, /* true if this is the last row for this
  1029. * variable, so terminate with ";" instead
  1030. * of "," */
  1031. const double *vals /* pointer to block of values */
  1032. )
  1033. {
  1034. long iel;
  1035. char sout[100]; /* temporary string for each encoded output */
  1036. for (iel = 0; iel < len-1; iel++) {
  1037. printdval(sout, fmt, vp, *vals++);
  1038. (void) strcat(sout, " ");
  1039. lput(sout);
  1040. }
  1041. printdval(sout, fmt, vp, *vals++);
  1042. lput(sout);
  1043. lastdelim2x (more, lastrow);
  1044. }
  1045. /* Output the data for a single variable, in NcML syntax. */
  1046. int
  1047. vardatax(
  1048. const ncvar_t *vp, /* variable */
  1049. size_t vdims[], /* variable dimension sizes */
  1050. int ncid, /* netcdf id */
  1051. int varid, /* variable id */
  1052. const fspec_t *fsp /* formatting specs */
  1053. )
  1054. {
  1055. size_t cor[NC_MAX_DIMS]; /* corner coordinates */
  1056. size_t edg[NC_MAX_DIMS]; /* edges of hypercube */
  1057. size_t add[NC_MAX_DIMS]; /* "odometer" increment to next "row" */
  1058. #define VALBUFSIZ 1000
  1059. double vals[VALBUFSIZ] ; /* aligned buffer */
  1060. int gulp = VALBUFSIZ;
  1061. int id;
  1062. int ir;
  1063. size_t nels;
  1064. size_t ncols;
  1065. size_t nrows;
  1066. int vrank = vp->ndims;
  1067. static int initeps = 0;
  1068. /* printf format used to print each value */
  1069. const char *fmt = get_fmt(ncid, varid, vp->type);
  1070. if (!initeps) { /* make sure epsilons get initialized */
  1071. init_epsilons();
  1072. initeps = 1;
  1073. }
  1074. nels = 1;
  1075. for (id = 0; id < vrank; id++) {
  1076. cor[id] = 0;
  1077. edg[id] = 1;
  1078. nels *= vdims[id]; /* total number of values for variable */
  1079. }
  1080. Printf(" <values>\n ");
  1081. set_indent (7);
  1082. if (vrank < 1) {
  1083. ncols = 1;
  1084. } else {
  1085. ncols = vdims[vrank-1]; /* size of "row" along last dimension */
  1086. edg[vrank-1] = vdims[vrank-1];
  1087. for (id = 0; id < vrank; id++)
  1088. add[id] = 0;
  1089. if (vrank > 1)
  1090. add[vrank-2] = 1;
  1091. }
  1092. nrows = nels/ncols; /* number of "rows" */
  1093. for (ir = 0; ir < nrows; ir++) {
  1094. /*
  1095. * rather than just printing a whole row at once (which might exceed
  1096. * the capacity of MSDOS platforms, for example), we break each row
  1097. * into smaller chunks, if necessary.
  1098. */
  1099. size_t corsav;
  1100. int left = (int)ncols;
  1101. boolean lastrow;
  1102. if (vrank > 0) {
  1103. corsav = cor[vrank-1];
  1104. }
  1105. lastrow = (boolean)(ir == nrows-1);
  1106. while (left > 0) {
  1107. size_t toget = left < gulp ? left : gulp;
  1108. if (vrank > 0)
  1109. edg[vrank-1] = toget;
  1110. switch(vp->type) {
  1111. case NC_CHAR:
  1112. NC_CHECK(
  1113. nc_get_vara_text(ncid, varid, cor, edg, (char *)vals) );
  1114. pr_tvalsx(toget, fmt, left > toget, lastrow,
  1115. (char *) vals, fsp);
  1116. break;
  1117. case NC_BYTE:
  1118. NC_CHECK(
  1119. nc_get_vara_schar(ncid, varid, cor, edg, (signed char *)vals) );
  1120. pr_bvalsx(vp, toget, fmt, left > toget, lastrow,
  1121. (signed char *) vals);
  1122. break;
  1123. case NC_SHORT:
  1124. NC_CHECK(
  1125. nc_get_vara_short(ncid, varid, cor, edg, (short *)vals) );
  1126. pr_svalsx(vp, toget, fmt, left > toget, lastrow,
  1127. (short *) vals);
  1128. break;
  1129. case NC_INT:
  1130. NC_CHECK(
  1131. nc_get_vara_int(ncid, varid, cor, edg, (int *)vals) );
  1132. pr_ivalsx(vp, toget, fmt, left > toget, lastrow,
  1133. (int *) vals);
  1134. break;
  1135. case NC_FLOAT:
  1136. NC_CHECK(
  1137. nc_get_vara_float(ncid, varid, cor, edg, (float *)vals) );
  1138. pr_fvalsx(vp, toget, fmt, left > toget, lastrow,
  1139. (float *) vals);
  1140. break;
  1141. case NC_DOUBLE:
  1142. NC_CHECK(
  1143. nc_get_vara_double(ncid, varid, cor, edg, (double *)vals) );
  1144. pr_dvalsx(vp, toget, fmt, left > toget, lastrow,
  1145. (double *) vals);
  1146. break;
  1147. #ifdef USE_NETCDF4
  1148. case NC_UBYTE:
  1149. /* TODO */
  1150. break;
  1151. case NC_USHORT:
  1152. /* TODO */
  1153. break;
  1154. case NC_UINT:
  1155. /* TODO */
  1156. break;
  1157. case NC_INT64:
  1158. /* TODO */
  1159. break;
  1160. case NC_UINT64:
  1161. /* TODO */
  1162. break;
  1163. case NC_STRING:
  1164. /* TODO */
  1165. break;
  1166. case NC_VLEN:
  1167. /* TODO */
  1168. break;
  1169. case NC_OPAQUE:
  1170. /* TODO */
  1171. break;
  1172. case NC_COMPOUND:
  1173. /* TODO */
  1174. break;
  1175. #endif /* USE_NETCDF4 */
  1176. default:
  1177. error("vardata: bad type");
  1178. }
  1179. left -= toget;
  1180. if (vrank > 0)
  1181. cor[vrank-1] += toget;
  1182. }
  1183. if (vrank > 0)
  1184. cor[vrank-1] = corsav;
  1185. if (ir < nrows-1)
  1186. if (!upcorner(vdims,vp->ndims,cor,add))
  1187. error("vardata: odometer overflowed!");
  1188. set_indent(2);
  1189. }
  1190. Printf(" </values>\n");
  1191. return 0;
  1192. }