/********************************************************************* * Copyright 1993, UCAR/Unidata * See netcdf/COPYRIGHT file for copying and redistribution conditions. * $Header: /upc/share/CVS/netcdf-3/ncdump/vardata.c,v 1.13 2006/03/04 18:50:15 ed Exp $ *********************************************************************/ #include #include #include #include #include #ifndef NO_FLOAT_H #include /* for FLT_EPSILON, DBL_EPSILON */ #endif /* NO_FLOAT_H */ #include #include "ncdump.h" #include "dumplib.h" #include "vardata.h" static float float_epsilon(void); static double double_epsilon(void); static void init_epsilons(void); static void printbval(char* sout, const char* fmt, const ncvar_t* varp, signed char val); static void printsval(char* sout, const char* fmt, const ncvar_t* varp, short val); static void printival(char* sout, const char* fmt, const ncvar_t* varp, int val); static void printfval(char* sout, const char* fmt, const ncvar_t* varp, float val); static void printdval(char* sout, const char* fmt, const ncvar_t* varp, double val); static void print_any_val(char *sout, const char *fmt, const ncvar_t *varp, const nc_type type, void *val); static void lastdelim(boolean more, boolean lastrow); static void annotate(const ncvar_t* vp, const fspec_t* fsp, const size_t* cor, long iel); static void pr_tvals(const ncvar_t *vp, size_t len, const char *fmt, boolean more, boolean lastrow, const char *vals, const fspec_t* fsp, const size_t *cor); static void pr_bvals(const ncvar_t *vp, size_t len, const char *fmt, boolean more, boolean lastrow, const signed char *vals, const fspec_t* fsp, const size_t *cor); static void pr_svals(const ncvar_t *vp, size_t len, const char *fmt, boolean more, boolean lastrow, const short *vals, const fspec_t* fsp, const size_t *cor); static void pr_ivals(const ncvar_t *vp, size_t len, const char *fmt, boolean more, boolean lastrow, const int *vals, const fspec_t* fsp, const size_t *cor); static void pr_fvals(const ncvar_t *vp, size_t len, const char *fmt, boolean more, boolean lastrow, const float *vals, const fspec_t* fsp, const size_t *cor); static void pr_dvals(const ncvar_t *vp, size_t len, const char *fmt, boolean more, boolean lastrow, const double *vals, const fspec_t* fsp, const size_t *cor); static int upcorner(const size_t* dims, int ndims, size_t* odom, const size_t* add); static void lastdelim2 (boolean more, boolean lastrow); #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) static float float_eps; static double double_eps; static float float_epsilon(void) { float float_eps; #ifndef NO_FLOAT_H float_eps = FLT_EPSILON; #else /* NO_FLOAT_H */ { float etop, ebot, eps; float one = 1.0; float two = 2.0; etop = 1.0; ebot = 0.0; eps = ebot + (etop - ebot)/two; while (eps != ebot && eps != etop) { float epsp1; epsp1 = one + eps; if (epsp1 > one) etop = eps; else ebot = eps; eps = ebot + (etop - ebot)/two; } float_eps = two * etop; } #endif /* NO_FLOAT_H */ return float_eps; } static double double_epsilon(void) { double double_eps; #ifndef NO_FLOAT_H double_eps = DBL_EPSILON; #else /* NO_FLOAT_H */ { double etop, ebot, eps; double one = 1.0; double two = 2.0; etop = 1.0; ebot = 0.0; eps = ebot + (etop - ebot)/two; while (eps != ebot && eps != etop) { double epsp1; epsp1 = one + eps; if (epsp1 > one) etop = eps; else ebot = eps; eps = ebot + (etop - ebot)/two; } double_eps = two * etop; } #endif /* NO_FLOAT_H */ return double_eps; } static void init_epsilons(void) { float_eps = float_epsilon(); double_eps = double_epsilon(); } /* * Output a value of a byte variable, except if there is a fill value for * the variable and the value is the fill value, print the fill-value string * instead. */ static void printbval( char *sout, /* string where output goes */ const char *fmt, /* printf format used for value */ const ncvar_t *varp, /* variable */ signed char val /* value */ ) { if (varp->has_fillval) { double fillval = varp->fillval; if(fillval == val) { (void) sprintf(sout, FILL_STRING); return; } } (void) sprintf(sout, fmt, val); } /* * Output a value of a short variable, except if there is a fill value for * the variable and the value is the fill value, print the fill-value string * instead. */ static void printsval( char *sout, /* string where output goes */ const char *fmt, /* printf format used for value */ const ncvar_t *varp, /* variable */ short val /* value */ ) { if (varp->has_fillval) { double fillval = varp->fillval; if(fillval == val) { (void) sprintf(sout, FILL_STRING); return; } } (void) sprintf(sout, fmt, val); } /* * Output a value of an int variable, except if there is a fill value for * the variable and the value is the fill value, print the fill-value string * instead. */ static void printival( char *sout, /* string where output goes */ const char *fmt, /* printf format used for value */ const ncvar_t *varp, /* variable */ int val /* value */ ) { if (varp->has_fillval) { int fillval = (int)varp->fillval; if(fillval == val) { (void) sprintf(sout, FILL_STRING); return; } } (void) sprintf(sout, fmt, val); } #define absval(x) ( (x) < 0 ? -(x) : (x) ) /* * Output a value of a float variable, except if there is a fill value for * the variable and the value is the fill value, print the fill-value string * instead. Floating-point fill values need only be within machine epsilon of * defined fill value. */ static void printfval( char *sout, /* string where output goes */ const char *fmt, /* printf format used for value */ const ncvar_t *varp, /* variable */ float val /* value */ ) { if(varp->has_fillval) { double fillval = varp->fillval; if((val > 0) == (fillval > 0) && /* prevents potential overflow */ (absval(val - fillval) <= absval(float_eps * fillval))) { (void) sprintf(sout, FILL_STRING); return; } } (void) sprintf(sout, fmt, val); } /* * Output a value of a double variable, except if there is a fill value for * the variable and the value is the fill value, print the fill-value string * instead. Floating-point fill values need only be within machine epsilon of * defined fill value. */ static void printdval( char *sout, /* string where output goes */ const char *fmt, /* printf format used for value */ const ncvar_t *varp, /* variable */ double val /* value */ ) { if(varp->has_fillval) { double fillval = varp->fillval; if((val > 0) == (fillval > 0) && /* prevents potential overflow */ (absval(val - fillval) <= absval(double_eps * fillval))) { (void) sprintf(sout, FILL_STRING); return; } } (void) sprintf(sout, fmt, val); } #ifdef USE_NETCDF4 /* * Output a value of a double variable, except if there is a fill value for * the variable and the value is the fill value, print the fill-value string * instead. Floating-point fill values need only be within machine epsilon of * defined fill value. */ static void print_any_val(char *sout, const char *fmt, const ncvar_t *varp, const nc_type type, void *val) { switch(type) { case NC_INT64: sprintf(sout, fmt, *(long long *)val); (long long *)val++; break; default: break; } /* if(varp->has_fillval) { */ /* double fillval = varp->fillval; */ /* if((val > 0) == (fillval > 0) && /\* prevents potential overflow *\/ */ /* (absval(val - fillval) <= absval(double_eps * fillval))) { */ /* (void) sprintf(sout, FILL_STRING); */ /* return; */ /* } */ /* } */ } #endif /* USE_NETCDF4 */ /* * print last delimiter in each line before annotation (, or ;) */ static void lastdelim (boolean more, boolean lastrow) { if (more) { Printf(", "); } else { if(lastrow) { Printf(";"); } else { Printf(","); } } } /* * print last delimiter in each line before annotation (, or ;) */ static void lastdelim2 (boolean more, boolean lastrow) { if (more) { lput(", "); } else { if(lastrow) { lput(" ;"); lput("\n"); } else { lput(",\n"); lput(" "); } } } /* * Annotates a value in data section with var name and indices in comment */ static void annotate( const ncvar_t *vp, /* variable */ const fspec_t* fsp, /* formatting specs */ const size_t *cor, /* corner coordinates */ long iel /* which element in current row */ ) { int vrank = vp->ndims; int id; /* print indices according to data_lang */ (void) printf(" // %s(", vp->name); switch (fsp->data_lang) { case LANG_C: /* C variable indices */ for (id = 0; id < vrank-1; id++) Printf("%lu,", (unsigned long) cor[id]); Printf("%lu", (unsigned long) cor[id] + iel); break; case LANG_F: /* Fortran variable indices */ Printf("%lu", (unsigned long) cor[vrank-1] + iel + 1); for (id = vrank-2; id >=0 ; id--) { Printf(",%lu", 1 + (unsigned long) cor[id]); } break; } Printf(")\n "); } /* * Print a number of char variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_tvals( const ncvar_t *vp, /* variable */ size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const char *vals, /* pointer to block of values */ const fspec_t* fsp, /* formatting specs */ const size_t *cor /* corner coordinates */ ) { long iel; const char *sp; unsigned char uc; char sout[100]; /* temporary string for each encoded output */ if (fmt == 0 || STREQ(fmt,"%s") || STREQ(fmt,"")) { /* as string */ Printf("\""); /* adjust len so trailing nulls don't get printed */ sp = vals + len; while (len != 0 && *--sp == '\0') len--; for (iel = 0; iel < len; iel++) switch (uc = *vals++ & 0377) { case '\b': Printf("\\b"); break; case '\f': Printf("\\f"); break; case '\n': /* generate linebreaks after new-lines */ Printf("\\n\",\n \""); break; case '\r': Printf("\\r"); break; case '\t': Printf("\\t"); break; case '\v': Printf("\\v"); break; case '\\': Printf("\\\\"); break; case '\'': Printf("\\\'"); break; case '\"': Printf("\\\""); break; default: if (isprint(uc)) Printf("%c",uc); else Printf("\\%.3o",uc); break; } Printf("\""); if (fsp->full_data_cmnts) { lastdelim (more, lastrow); annotate (vp, fsp, (size_t *)cor, 0L); } } else { /* use format from C_format attribute */ for (iel = 0; iel < len-1; iel++) { if (fsp->full_data_cmnts) { Printf(fmt, *vals++); Printf(", "); annotate (vp, fsp, (size_t *)cor, iel); } else { (void) sprintf(sout, fmt, *vals++); (void) strcat(sout, ", "); lput(sout); } } if (fsp->full_data_cmnts) { Printf(fmt, *vals++); lastdelim (more, lastrow); annotate (vp, fsp, (size_t *)cor, iel); } else { (void) sprintf(sout, fmt, *vals++); lput(sout); } } if (!fsp->full_data_cmnts) { lastdelim2 (more, lastrow); } } /* * Print a number of byte variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_bvals( const ncvar_t *vp, /* variable */ size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const signed char *vals, /* pointer to block of values */ const fspec_t* fsp, /* formatting specs */ const size_t *cor /* corner coordinates */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printbval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf(sout); Printf(","); annotate (vp, fsp, cor, iel); } else { (void) strcat(sout, ", "); lput(sout); } } printbval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf(sout); lastdelim (more, lastrow); annotate (vp, fsp, cor, iel); } else { lput(sout); lastdelim2 (more, lastrow); } } /* * Print a number of short variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_svals( const ncvar_t *vp, /* variable */ size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const short *vals, /* pointer to block of values */ const fspec_t* fsp, /* formatting specs */ const size_t *cor /* corner coordinates */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printsval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf(sout); Printf(","); annotate (vp, fsp, cor, iel); } else { (void) strcat(sout, ", "); lput(sout); } } printsval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf(sout); lastdelim (more, lastrow); annotate (vp, fsp, cor, iel); } else { lput(sout); lastdelim2 (more, lastrow); } } /* * Print a number of int variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_ivals( const ncvar_t *vp, /* variable */ size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const int *vals, /* pointer to block of values */ const fspec_t* fsp, /* formatting specs */ const size_t *cor /* corner coordinates */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printival(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf(sout); Printf(","); annotate (vp, fsp, cor, iel); } else { (void) strcat(sout, ", "); lput(sout); } } printival(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf(sout); lastdelim (more, lastrow); annotate (vp, fsp, cor, iel); } else { lput(sout); lastdelim2 (more, lastrow); } } /* * Print a number of float variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_fvals( const ncvar_t *vp, /* variable */ size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const float *vals, /* pointer to block of values */ const fspec_t* fsp, /* formatting specs */ const size_t *cor /* corner coordinates */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printfval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf(sout); Printf(","); annotate (vp, fsp, cor, iel); } else { (void) strcat(sout, ", "); lput(sout); } } printfval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf(sout); lastdelim (more, lastrow); annotate (vp, fsp, cor, iel); } else { lput(sout); lastdelim2 (more, lastrow); } } /* * Print a number of double variable values, where the optional comments * for each value identify the variable, and each dimension index. */ static void pr_dvals( const ncvar_t *vp, /* variable */ size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const double *vals, /* pointer to block of values */ const fspec_t* fsp, /* formatting specs */ const size_t *cor /* corner coordinates */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printdval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf(sout); Printf(","); annotate (vp, fsp, cor, iel); } else { (void) strcat(sout, ", "); lput(sout); } } printdval(sout, fmt, vp, *vals++); if (fsp->full_data_cmnts) { Printf(sout); lastdelim (more, lastrow); annotate (vp, fsp, cor, iel); } else { lput(sout); lastdelim2 (more, lastrow); } } #ifdef USE_NETCDF4 #define MAX_OUTPUT_LEN 100 /* Print a number of variable values of any type, where the optional * comments for each value identify the variable, and each dimension * index. */ static void pr_any_vals(const ncvar_t *vp, size_t len, const char *fmt, boolean more, boolean lastrow, void *vals, const fspec_t* fsp, const size_t *cor, const nc_type type) { long iel; char sout[MAX_OUTPUT_LEN]; /* temporary string for each encoded output */ /* Print eah value. */ for (iel = 0; iel < len-1; iel++) { print_any_val(sout, fmt, vp, type, vals); if (fsp->full_data_cmnts) { Printf(sout); Printf(","); annotate (vp, fsp, cor, iel); } else { (void) strcat(sout, ", "); lput(sout); } } print_any_val(sout, fmt, vp, type, vals); if (fsp->full_data_cmnts) { Printf(sout); lastdelim (more, lastrow); annotate (vp, fsp, cor, iel); } else { lput(sout); lastdelim2 (more, lastrow); } } #endif /* USE_NETCDF4 */ /* * Updates a vector of ints, odometer style. Returns 0 if odometer * overflowed, else 1. */ static int upcorner( const size_t *dims, /* The "odometer" limits for each dimension */ int ndims, /* Number of dimensions */ size_t* odom, /* The "odometer" vector to be updated */ const size_t* add /* A vector to "add" to odom on each update */ ) { int id; int ret = 1; for (id = ndims-1; id > 0; id--) { odom[id] += add[id]; if(odom[id] >= dims[id]) { odom[id-1]++; odom[id] -= dims[id]; } } odom[0] += add[0]; if (odom[0] >= dims[0]) ret = 0; return ret; } /* Output the data for a single variable, in CDL syntax. */ int vardata( const ncvar_t *vp, /* variable */ size_t vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid, /* variable id */ const fspec_t* fsp /* formatting specs */ ) { size_t cor[NC_MAX_DIMS]; /* corner coordinates */ size_t edg[NC_MAX_DIMS]; /* edges of hypercube */ size_t add[NC_MAX_DIMS]; /* "odometer" increment to next "row" */ #define VALBUFSIZ 1000 double vals[VALBUFSIZ] ; /* aligned buffer */ int gulp = VALBUFSIZ; int id; int ir; size_t nels; size_t ncols; size_t nrows; int vrank = vp->ndims; static int initeps = 0; /* printf format used to print each value */ const char *fmt = get_fmt(ncid, varid, vp->type); if (!initeps) { /* make sure epsilons get initialized */ init_epsilons(); initeps = 1; } nels = 1; for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } if (vrank <= 1) { Printf("\n %s = ", vp->name); set_indent ((int)strlen(vp->name) + 4); } else { Printf("\n %s =\n ", vp->name); set_indent (2); } if (vrank < 1) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = vdims[vrank-1]; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ for (ir = 0; ir < nrows; ir++) { /* * rather than just printing a whole row at once (which might exceed * the capacity of MSDOS platforms, for example), we break each row * into smaller chunks, if necessary. */ size_t corsav; int left = (int)ncols; boolean lastrow; if (vrank > 0) { corsav = cor[vrank-1]; if (fsp->brief_data_cmnts != false && vrank > 1 && left > 0) { /* print brief comment with indices range */ Printf("// %s(",vp->name); switch (fsp->data_lang) { case LANG_C: /* print brief comment with C variable indices */ for (id = 0; id < vrank-1; id++) Printf("%lu,", (unsigned long)cor[id]); if (vdims[vrank-1] == 1) Printf("0"); else Printf(" 0-%lu", (unsigned long)vdims[vrank-1]-1); break; case LANG_F: /* print brief comment with Fortran variable indices */ if (vdims[vrank-1] == 1) Printf("1"); else Printf("1-%lu ", (unsigned long)vdims[vrank-1]); for (id = vrank-2; id >=0 ; id--) { Printf(",%lu", (unsigned long)(1 + cor[id])); } break; } Printf(")\n "); set_indent(4); } } lastrow = (boolean)(ir == nrows-1); while (left > 0) { size_t toget = left < gulp ? left : gulp; if (vrank > 0) edg[vrank-1] = toget; switch(vp->type) { case NC_CHAR: NC_CHECK( nc_get_vara_text(ncid, varid, cor, edg, (char *)vals) ); pr_tvals(vp, toget, fmt, left > toget, lastrow, (char *) vals, fsp, cor); break; case NC_BYTE: NC_CHECK( nc_get_vara_schar(ncid, varid, cor, edg, (signed char *)vals) ); pr_bvals(vp, toget, fmt, left > toget, lastrow, (signed char *) vals, fsp, cor); break; case NC_SHORT: NC_CHECK( nc_get_vara_short(ncid, varid, cor, edg, (short *)vals) ); pr_svals(vp, toget, fmt, left > toget, lastrow, (short *) vals, fsp, cor); break; case NC_INT: NC_CHECK( nc_get_vara_int(ncid, varid, cor, edg, (int *)vals) ); pr_ivals(vp, toget, fmt, left > toget, lastrow, (int *) vals, fsp, cor); break; case NC_FLOAT: NC_CHECK( nc_get_vara_float(ncid, varid, cor, edg, (float *)vals) ); pr_fvals(vp, toget, fmt, left > toget, lastrow, (float *) vals, fsp, cor); break; case NC_DOUBLE: NC_CHECK( nc_get_vara_double(ncid, varid, cor, edg, (double *)vals) ); pr_dvals(vp, toget, fmt, left > toget, lastrow, (double *) vals, fsp, cor); break; #ifdef USE_NETCDF4 case NC_INT64: NC_CHECK( nc_get_vara(ncid, varid, cor, edg, vals) ); pr_any_vals(vp, toget, fmt, left > toget, lastrow, vals, fsp, cor, vp->type); break; #endif /* USE_NETCDF4 */ default: error("vardata: bad type"); } left -= toget; if (vrank > 0) cor[vrank-1] += toget; } if (vrank > 0) cor[vrank-1] = corsav; if (ir < nrows-1) if (!upcorner(vdims,vp->ndims,cor,add)) error("vardata: odometer overflowed!"); set_indent(2); } return 0; } /* * print last delimiter in each line before annotation (, or ;) */ static void lastdelim2x (boolean more, boolean lastrow) { if (more) { lput(" "); } else { if(lastrow) { lput("\n "); } else { lput("\n "); } } } /* * Print a number of char variable values. */ static void pr_tvalsx( size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const char *vals, /* pointer to block of values */ const fspec_t *fsp /* formatting specs */ ) { long iel; const char *sp; unsigned char uc; char sout[100]; /* temporary string for each encoded output */ if (fmt == 0 || STREQ(fmt,"%s") || STREQ(fmt,"")) { /* as string */ Printf("\""); /* adjust len so trailing nulls don't get printed */ sp = vals + len; while (len != 0 && *--sp == '\0') len--; for (iel = 0; iel < len; iel++) switch (uc = *vals++ & 0377) { case '\b': Printf("\\b"); break; case '\f': Printf("\\f"); break; case '\n': /* generate linebreaks after new-lines */ Printf("\\n\",\n \""); break; case '\r': Printf("\\r"); break; case '\t': Printf("\\t"); break; case '\v': Printf("\\v"); break; case '\\': Printf("\\\\"); break; case '\'': Printf("\\\'"); break; case '\"': Printf("\\\""); break; default: if (isprint(uc)) Printf("%c",uc); else Printf("\\%.3o",uc); break; } Printf("\""); } else { /* use format from C_format attribute */ for (iel = 0; iel < len-1; iel++) { (void) sprintf(sout, fmt, *vals++); (void) strcat(sout, " "); lput(sout); } (void) sprintf(sout, fmt, *vals++); lput(sout); } if (!fsp->full_data_cmnts) { lastdelim2x (more, lastrow); } } /* * Print a number of byte variable values. */ static void pr_bvalsx( const ncvar_t *vp, /* variable */ size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const signed char *vals /* pointer to block of values */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printbval(sout, fmt, vp, *vals++); (void) strcat(sout, " "); lput(sout); } printbval(sout, fmt, vp, *vals++); lput(sout); lastdelim2x (more, lastrow); } /* * Print a number of short variable values. */ static void pr_svalsx( const ncvar_t *vp, /* variable */ size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const short *vals /* pointer to block of values */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printsval(sout, fmt, vp, *vals++); (void) strcat(sout, " "); lput(sout); } printsval(sout, fmt, vp, *vals++); lput(sout); lastdelim2x (more, lastrow); } /* * Print a number of int variable values. */ static void pr_ivalsx( const ncvar_t *vp, /* variable */ size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const int *vals /* pointer to block of values */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printival(sout, fmt, vp, *vals++); (void) strcat(sout, " "); lput(sout); } printival(sout, fmt, vp, *vals++); lput(sout); lastdelim2x (more, lastrow); } /* * Print a number of float variable values. */ static void pr_fvalsx( const ncvar_t *vp, /* variable */ size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const float *vals /* pointer to block of values */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printfval(sout, fmt, vp, *vals++); (void) strcat(sout, " "); lput(sout); } printfval(sout, fmt, vp, *vals++); lput(sout); lastdelim2x (more, lastrow); } /* * Print a number of double variable values. */ static void pr_dvalsx( const ncvar_t *vp, /* variable */ size_t len, /* number of values to print */ const char *fmt, /* printf format used for each value. If * nc_type is NC_CHAR and this is NULL, * character arrays will be printed as * strings enclosed in quotes. */ boolean more, /* true if more data for this row will * follow, so add trailing comma */ boolean lastrow, /* true if this is the last row for this * variable, so terminate with ";" instead * of "," */ const double *vals /* pointer to block of values */ ) { long iel; char sout[100]; /* temporary string for each encoded output */ for (iel = 0; iel < len-1; iel++) { printdval(sout, fmt, vp, *vals++); (void) strcat(sout, " "); lput(sout); } printdval(sout, fmt, vp, *vals++); lput(sout); lastdelim2x (more, lastrow); } /* Output the data for a single variable, in NcML syntax. */ int vardatax( const ncvar_t *vp, /* variable */ size_t vdims[], /* variable dimension sizes */ int ncid, /* netcdf id */ int varid, /* variable id */ const fspec_t *fsp /* formatting specs */ ) { size_t cor[NC_MAX_DIMS]; /* corner coordinates */ size_t edg[NC_MAX_DIMS]; /* edges of hypercube */ size_t add[NC_MAX_DIMS]; /* "odometer" increment to next "row" */ #define VALBUFSIZ 1000 double vals[VALBUFSIZ] ; /* aligned buffer */ int gulp = VALBUFSIZ; int id; int ir; size_t nels; size_t ncols; size_t nrows; int vrank = vp->ndims; static int initeps = 0; /* printf format used to print each value */ const char *fmt = get_fmt(ncid, varid, vp->type); if (!initeps) { /* make sure epsilons get initialized */ init_epsilons(); initeps = 1; } nels = 1; for (id = 0; id < vrank; id++) { cor[id] = 0; edg[id] = 1; nels *= vdims[id]; /* total number of values for variable */ } Printf(" \n "); set_indent (7); if (vrank < 1) { ncols = 1; } else { ncols = vdims[vrank-1]; /* size of "row" along last dimension */ edg[vrank-1] = vdims[vrank-1]; for (id = 0; id < vrank; id++) add[id] = 0; if (vrank > 1) add[vrank-2] = 1; } nrows = nels/ncols; /* number of "rows" */ for (ir = 0; ir < nrows; ir++) { /* * rather than just printing a whole row at once (which might exceed * the capacity of MSDOS platforms, for example), we break each row * into smaller chunks, if necessary. */ size_t corsav; int left = (int)ncols; boolean lastrow; if (vrank > 0) { corsav = cor[vrank-1]; } lastrow = (boolean)(ir == nrows-1); while (left > 0) { size_t toget = left < gulp ? left : gulp; if (vrank > 0) edg[vrank-1] = toget; switch(vp->type) { case NC_CHAR: NC_CHECK( nc_get_vara_text(ncid, varid, cor, edg, (char *)vals) ); pr_tvalsx(toget, fmt, left > toget, lastrow, (char *) vals, fsp); break; case NC_BYTE: NC_CHECK( nc_get_vara_schar(ncid, varid, cor, edg, (signed char *)vals) ); pr_bvalsx(vp, toget, fmt, left > toget, lastrow, (signed char *) vals); break; case NC_SHORT: NC_CHECK( nc_get_vara_short(ncid, varid, cor, edg, (short *)vals) ); pr_svalsx(vp, toget, fmt, left > toget, lastrow, (short *) vals); break; case NC_INT: NC_CHECK( nc_get_vara_int(ncid, varid, cor, edg, (int *)vals) ); pr_ivalsx(vp, toget, fmt, left > toget, lastrow, (int *) vals); break; case NC_FLOAT: NC_CHECK( nc_get_vara_float(ncid, varid, cor, edg, (float *)vals) ); pr_fvalsx(vp, toget, fmt, left > toget, lastrow, (float *) vals); break; case NC_DOUBLE: NC_CHECK( nc_get_vara_double(ncid, varid, cor, edg, (double *)vals) ); pr_dvalsx(vp, toget, fmt, left > toget, lastrow, (double *) vals); break; #ifdef USE_NETCDF4 case NC_UBYTE: /* TODO */ break; case NC_USHORT: /* TODO */ break; case NC_UINT: /* TODO */ break; case NC_INT64: /* TODO */ break; case NC_UINT64: /* TODO */ break; case NC_STRING: /* TODO */ break; case NC_VLEN: /* TODO */ break; case NC_OPAQUE: /* TODO */ break; case NC_COMPOUND: /* TODO */ break; #endif /* USE_NETCDF4 */ default: error("vardata: bad type"); } left -= toget; if (vrank > 0) cor[vrank-1] += toget; } if (vrank > 0) cor[vrank-1] = corsav; if (ir < nrows-1) if (!upcorner(vdims,vp->ndims,cor,add)) error("vardata: odometer overflowed!"); set_indent(2); } Printf(" \n"); return 0; }