00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #define REDEF
00020
00021
00022 #undef NDEBUG
00023
00024 #include <config.h>
00025 #include <stdio.h>
00026 #include <stddef.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <assert.h>
00030
00031 #ifdef USE_NETCDF4
00032 #include <netcdf3.h>
00033 #include <nc3convert.h>
00034 #else
00035 #include "netcdf.h"
00036 #endif
00037
00038 #define MAXSHORT 32767
00039 #define MAXINT 2147483647
00040 #define MAXBYTE 127
00041
00042
00043 #define FNAME "test.nc"
00044 #define NUM_DIMS 3
00045 #define DONT_CARE -1
00046
00047 #define NUM_RECS 8
00048 #define SIZE_1 7
00049 #define SIZE_2 8
00050
00051 static struct {
00052 int num_dims;
00053 int num_vars;
00054 int num_attrs;
00055 int xtendim;
00056 } cdesc[1];
00057
00058 static struct {
00059 char mnem[NC_MAX_NAME];
00060 nc_type type;
00061 int ndims;
00062 int dims[NC_MAX_DIMS];
00063 int num_attrs;
00064 } vdesc[1];
00065
00066 static struct {
00067 char mnem[NC_MAX_NAME];
00068 nc_type type;
00069 size_t len;
00070 } adesc[1];
00071
00072 union getret
00073 {
00074 char by[8];
00075 short sh[4];
00076 int in[2];
00077 float fl[2];
00078 double dbl;
00079 };
00080
00081
00082 static void
00083 chkgot(nc_type type, union getret got, double check)
00084 {
00085 switch(type){
00086 case NC_BYTE :
00087 assert( (char)check == got.by[0] );
00088 break;
00089 case NC_CHAR :
00090 assert( (char)check == got.by[0] );
00091 break;
00092 case NC_SHORT :
00093 assert( (short)check == got.sh[0] );
00094 break;
00095 case NC_INT :
00096 assert( (int)check == got.in[0] );
00097 break;
00098 case NC_FLOAT :
00099 assert( (float)check == got.fl[0] );
00100 break;
00101 case NC_DOUBLE :
00102 assert( check == got.dbl );
00103 break;
00104 default:
00105 break;
00106 }
00107 }
00108
00109 static const char *fname = FNAME;
00110
00111
00112 static size_t num_dims = NUM_DIMS;
00113 static size_t sizes[] = { NC_UNLIMITED, SIZE_1 , SIZE_2 };
00114 static const char * const dim_names[] = { "record", "ixx", "iyy"};
00115
00116 static void
00117 createtestdims(int cdfid, size_t num_dims, const size_t *sizes, const char * const dim_names[])
00118 {
00119 int dimid;
00120 while(num_dims-- != 0)
00121 {
00122 assert( nc_def_dim(cdfid, *dim_names++, *sizes, &dimid)
00123 == NC_NOERR);
00124 sizes++;
00125 }
00126
00127 }
00128
00129
00130 static void
00131 testdims(int cdfid, size_t num_dims, size_t *sizes, const char * const dim_names[])
00132 {
00133 int ii;
00134 size_t size;
00135 char cp[NC_MAX_NAME];
00136 for(ii=0; (size_t) ii < num_dims; ii++, sizes++)
00137 {
00138 assert( nc_inq_dim(cdfid, ii, cp, &size) == NC_NOERR);
00139 if( size != *sizes)
00140 (void) fprintf(stderr, "%d: %lu != %lu\n",
00141 ii, (unsigned long)size, (unsigned long)*sizes);
00142 assert( size == *sizes);
00143 assert( strcmp(cp, *dim_names++) == 0);
00144 }
00145
00146 }
00147
00148
00149
00150 static const char * const reqattr[] = {
00151 "UNITS",
00152 "VALIDMIN",
00153 "VALIDMAX",
00154 "SCALEMIN",
00155 "SCALEMAX",
00156 "FIELDNAM",
00157 _FillValue
00158 };
00159 #define NUM_RATTRS 6
00160
00161 static struct tcdfvar {
00162 const char *mnem;
00163 nc_type type;
00164 const char *fieldnam;
00165 double validmin;
00166 double validmax;
00167 double scalemin;
00168 double scalemax;
00169 const char *units;
00170 int ndims;
00171 int dims[NUM_DIMS];
00172 } const testvars[] = {
00173 #define Byte_id 0
00174 { "Byte", NC_BYTE, "Byte sized integer variable",
00175 -MAXBYTE, MAXBYTE, -MAXBYTE, MAXBYTE , "ones",
00176 2, {0,1,DONT_CARE} },
00177 #define Char_id 1
00178 { "Char", NC_CHAR, "char (string) variable",
00179 DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, "(unitless)",
00180 2, {0,2,DONT_CARE} },
00181 #define Short_id 2
00182 { "Short", NC_SHORT, "Short variable",
00183 -MAXSHORT, MAXSHORT, -MAXSHORT, MAXSHORT , "ones",
00184 2, {0, 2, DONT_CARE }},
00185 #define Long_id 3
00186 { "Long", NC_INT, "Long Integer variable",
00187 -MAXINT, MAXINT, -MAXINT, MAXINT, "ones",
00188 2, {1, 2, DONT_CARE}},
00189 #define Float_id 4
00190 { "Float", NC_FLOAT, "Single Precision Floating Point variable",
00191 -MAXINT, MAXINT, -MAXINT, MAXINT, "flots",
00192 3, {0, 1, 2 }},
00193 #define Double_id 5
00194 { "Double", NC_DOUBLE, "Double Precision Floating Point variable",
00195 -MAXINT, MAXINT, -MAXINT, MAXINT, "dflots",
00196 3, {0, 1, 2 }},
00197 };
00198 #define NUM_TESTVARS 6
00199
00200 static void
00201 createtestvars(int id, const struct tcdfvar *testvars, size_t count)
00202 {
00203 int ii;
00204 int varid;
00205 const struct tcdfvar *vp = testvars;
00206
00207 for(ii = 0; (size_t) ii < count; ii++, vp++ )
00208 {
00209 assert(nc_def_var(id, vp->mnem, vp->type, vp->ndims, vp->dims,
00210 &varid)
00211 == NC_NOERR );
00212
00213 assert(
00214 nc_put_att_text(id,ii,reqattr[0],strlen(vp->units),
00215 vp->units)
00216 == NC_NOERR);
00217 assert(
00218 nc_put_att_double(id,ii,reqattr[1],NC_DOUBLE,1,
00219 &vp->validmin)
00220 == NC_NOERR);
00221 assert(
00222 nc_put_att_double(id,ii,reqattr[2],NC_DOUBLE,1,
00223 &vp->validmax)
00224 == NC_NOERR);
00225 assert(
00226 nc_put_att_double(id,ii,reqattr[3],NC_DOUBLE,1,
00227 &vp->scalemin)
00228 == NC_NOERR);
00229 assert(
00230 nc_put_att_double(id,ii,reqattr[4],NC_DOUBLE,1,
00231 &vp->scalemax)
00232 == NC_NOERR);
00233 assert(
00234 nc_put_att_text(id,ii,reqattr[5],strlen(vp->fieldnam),
00235 vp->fieldnam)
00236 == NC_NOERR);
00237 }
00238 }
00239
00240 static void
00241 parray(const char *label, size_t count, const size_t array[])
00242 {
00243 (void) fprintf(stdout, "%s", label);
00244 (void) fputc('\t',stdout);
00245 for(; count != 0; count--, array++)
00246 (void) fprintf(stdout," %lu", (unsigned long) *array);
00247 }
00248
00249
00250 static void
00251 fill_seq(int id)
00252 {
00253 float values[NUM_RECS * SIZE_1 * SIZE_2];
00254 size_t vindices[NUM_DIMS];
00255
00256 {
00257 size_t ii = 0;
00258 for(; ii < sizeof(values)/sizeof(values[0]); ii++)
00259 {
00260 values[ii] = (float) ii;
00261 }
00262 }
00263
00264
00265 {
00266 size_t *cc = vindices;
00267 while (cc < &vindices[num_dims])
00268 *cc++ = 0;
00269 }
00270
00271 sizes[0] = NUM_RECS;
00272
00273 assert( nc_put_vara_float(id, Float_id, vindices, sizes, values)== NC_NOERR);
00274
00275 }
00276
00277 static void
00278 check_fill_seq(int id)
00279 {
00280 size_t vindices[NUM_DIMS];
00281 size_t *cc, *mm;
00282 union getret got;
00283 int ii = 0;
00284 float val;
00285
00286 sizes[0] = NUM_RECS;
00287 cc = vindices;
00288 while (cc < &vindices[num_dims])
00289 *cc++ = 0;
00290
00291
00292 cc = vindices;
00293 mm = sizes;
00294 while (*vindices < *sizes)
00295 {
00296 while (*cc < *mm)
00297 {
00298 if (mm == &sizes[num_dims - 1])
00299 {
00300 if(nc_get_var1_float(id, Float_id, vindices, &got.fl[0]) == -1)
00301 goto bad_ret;
00302 val = (float) ii;
00303 if(val != got.fl[0])
00304 {
00305 parray("indices", NUM_DIMS, vindices);
00306 (void) printf("\t%f != %f\n", val, got.fl[0]);
00307 }
00308 (*cc)++; ii++;
00309 continue;
00310 }
00311 cc++;
00312 mm++;
00313 }
00314 if(cc == vindices)
00315 break;
00316 *cc = 0;
00317 cc--;
00318 mm--;
00319 (*cc)++;
00320 }
00321 return;
00322 bad_ret :
00323 (void) printf("couldn't get a var in check_fill_seq() %d\n",
00324 ii);
00325 return;
00326 }
00327
00328 static const size_t indices[][3] = {
00329 {0, 1, 3},
00330 {0, 3, 0},
00331 {1, 2, 3},
00332 {3, 2, 1},
00333 {2, 1, 3},
00334 {1, 0, 0},
00335 {0, 0, 0},
00336 };
00337
00338 static const char chs[] = {'A','B', ((char)0xff) };
00339 static const size_t s_start[] = {0,1};
00340 static const size_t s_edges[] = {NUM_RECS, SIZE_1 - 1};
00341 static char sentence[NUM_RECS* SIZE_1 -1] =
00342 "The red death had long devastated the country.";
00343 static const short shs[] = {97, 99};
00344 static const int birthday = 82555;
00345 #define M_E 2.7182818284590452354
00346 static const float e = (float) M_E;
00347 static const double pinot = 3.25;
00348 static const double zed = 0.0;
00349
00350
00351
00352 int
00353 main(int ac, char *av[])
00354 {
00355 int ret;
00356 int id;
00357 char buf[256];
00358 #ifdef SYNCDEBUG
00359 char *str = "one";
00360 #endif
00361 int ii;
00362 size_t ui;
00363 const struct tcdfvar *tvp = testvars;
00364 union getret got;
00365 const size_t initialsz = 8192;
00366 size_t chunksz = 8192;
00367 size_t align = 8192/32;
00368
00369 ret = nc__create(fname,NC_NOCLOBBER, initialsz, &chunksz, &id);
00370 if(ret != NC_NOERR) {
00371 (void) fprintf(stderr, "trying again\n");
00372 ret = nc__create(fname,NC_CLOBBER, initialsz, &chunksz, &id);
00373 }
00374 if(ret != NC_NOERR)
00375 exit(ret);
00376
00377 assert( nc_put_att_text(id, NC_GLOBAL,
00378 "TITLE", 12, "another name") == NC_NOERR);
00379 assert( nc_get_att_text(id, NC_GLOBAL,
00380 "TITLE", buf) == NC_NOERR);
00381
00382 assert( nc_put_att_text(id, NC_GLOBAL,
00383 "TITLE", strlen(fname), fname) == NC_NOERR);
00384 assert( nc_get_att_text(id, NC_GLOBAL,
00385 "TITLE", buf) == NC_NOERR);
00386 buf[strlen(fname)] = 0;
00387
00388 assert( strcmp(fname, buf) == 0);
00389
00390 createtestdims(id, NUM_DIMS, sizes, dim_names);
00391 testdims(id, NUM_DIMS, sizes, dim_names);
00392
00393 createtestvars(id, testvars, NUM_TESTVARS);
00394
00395 {
00396 int ifill = -1; double dfill = -9999;
00397 assert( nc_put_att_int(id, Long_id,
00398 _FillValue, NC_INT, 1, &ifill) == NC_NOERR);
00399 assert( nc_put_att_double(id, Double_id,
00400 _FillValue, NC_DOUBLE, 1, &dfill) == NC_NOERR);
00401 }
00402
00403 #ifdef REDEF
00404 assert( nc__enddef(id, 0, align, 0, 2*align) == NC_NOERR );
00405 assert( nc_put_var1_int(id, Long_id, indices[3], &birthday)
00406 == NC_NOERR );
00407 fill_seq(id);
00408 assert( nc_redef(id) == NC_NOERR );
00409
00410 #endif
00411
00412 assert( nc_rename_dim(id,1, "IXX") == NC_NOERR);
00413 assert( nc_inq_dim(id, 1, buf, &ui) == NC_NOERR);
00414 (void) printf("dimrename: %s\n", buf);
00415 assert( nc_rename_dim(id,1, dim_names[1]) == NC_NOERR);
00416
00417 #ifdef ATTRX
00418 assert( nc_rename_att(id, 1, "UNITS", "units") == NC_NOERR);
00419 assert( nc_del_att(id, 4, "FIELDNAM")== NC_NOERR);
00420 assert( nc_del_att(id, 2, "SCALEMIN")== NC_NOERR);
00421 assert( nc_del_att(id, 2, "SCALEMAX")== NC_NOERR);
00422 #endif
00423
00424 assert( nc__enddef(id, 0, align, 0, 2*align) == NC_NOERR );
00425
00426 #ifndef REDEF
00427 fill_seq(id);
00428 assert( nc_put_var1_int(id, Long_id, indices[3], &birthday)== NC_NOERR );
00429 #endif
00430
00431 assert( nc_put_vara_schar(id, Byte_id, s_start, s_edges,
00432 (signed char *)sentence)
00433 == NC_NOERR);
00434 assert( nc_put_var1_schar(id, Byte_id, indices[6], (signed char *)(chs+1))
00435 == NC_NOERR);
00436 assert( nc_put_var1_schar(id, Byte_id, indices[5], (signed char *)chs)
00437 == NC_NOERR);
00438
00439 assert( nc_put_vara_text(id, Char_id, s_start, s_edges, sentence)
00440 == NC_NOERR);
00441 assert( nc_put_var1_text(id, Char_id, indices[6], (chs+1))
00442 == NC_NOERR) ;
00443 assert( nc_put_var1_text(id, Char_id, indices[5], chs)
00444 == NC_NOERR);
00445
00446 assert( nc_put_var1_short(id, Short_id, indices[4], shs)
00447 == NC_NOERR);
00448
00449 assert( nc_put_var1_float(id, Float_id, indices[2], &e)
00450 == NC_NOERR);
00451
00452 assert( nc_put_var1_double(id, Double_id, indices[1], &zed)
00453 == NC_NOERR);
00454 assert( nc_put_var1_double(id, Double_id, indices[0], &pinot)
00455 == NC_NOERR);
00456
00457
00458 #ifdef SYNCDEBUG
00459 (void) printf("Hit Return to sync\n");
00460 gets(str);
00461 nc_sync(id,0);
00462 (void) printf("Sync done. Hit Return to continue\n");
00463 gets(str);
00464 #endif
00465
00466 ret = nc_close(id);
00467 (void) printf("nc_close ret = %d\n\n", ret);
00468
00469
00470
00471
00472
00473 ret = nc__open(fname,NC_NOWRITE, &chunksz, &id);
00474 if(ret != NC_NOERR)
00475 {
00476 (void) printf("Could not open %s: %s\n", fname,
00477 nc_strerror(ret));
00478 exit(1);
00479 }
00480 (void) printf("reopen id = %d for filename %s\n",
00481 id, fname);
00482
00483
00484 (void) printf("NC ");
00485 assert( nc_inq(id, &(cdesc->num_dims), &(cdesc->num_vars),
00486 &(cdesc->num_attrs), &(cdesc->xtendim) ) == NC_NOERR);
00487 assert((size_t) cdesc->num_dims == num_dims);
00488 assert(cdesc->num_attrs == 1);
00489 assert(cdesc->num_vars == NUM_TESTVARS);
00490 (void) printf("done\n");
00491
00492
00493 (void) printf("GATTR ");
00494
00495 assert( nc_inq_attname(id, NC_GLOBAL, 0, adesc->mnem) == 0);
00496 assert(strcmp("TITLE",adesc->mnem) == 0);
00497 assert( nc_inq_att(id, NC_GLOBAL, adesc->mnem, &(adesc->type), &(adesc->len))== NC_NOERR);
00498 assert( adesc->type == NC_CHAR );
00499 assert( adesc->len == strlen(fname) );
00500 assert( nc_get_att_text(id, NC_GLOBAL, "TITLE", buf)== NC_NOERR);
00501 buf[adesc->len] = 0;
00502 assert( strcmp(fname, buf) == 0);
00503
00504
00505 (void) printf("VAR ");
00506 assert( cdesc->num_vars == NUM_TESTVARS );
00507
00508 for(ii = 0; ii < cdesc->num_vars; ii++, tvp++ )
00509 {
00510 int jj;
00511 assert( nc_inq_var(id, ii,
00512 vdesc->mnem,
00513 &(vdesc->type),
00514 &(vdesc->ndims),
00515 vdesc->dims,
00516 &(vdesc->num_attrs)) == NC_NOERR);
00517 if(strcmp(tvp->mnem , vdesc->mnem) != 0)
00518 {
00519 (void) printf("attr %d mnem mismatch %s, %s\n",
00520 ii, tvp->mnem, vdesc->mnem);
00521 continue;
00522 }
00523 if(tvp->type != vdesc->type)
00524 {
00525 (void) printf("attr %d type mismatch %d, %d\n",
00526 ii, (int)tvp->type, (int)vdesc->type);
00527 continue;
00528 }
00529 for(jj = 0; jj < vdesc->ndims; jj++ )
00530 {
00531 if(tvp->dims[jj] != vdesc->dims[jj] )
00532 {
00533 (void) printf(
00534 "inconsistent dim[%d] for variable %d: %d != %d\n",
00535 jj, ii, tvp->dims[jj], vdesc->dims[jj] );
00536 continue;
00537 }
00538 }
00539
00540
00541 (void) printf("VATTR\n");
00542 for(jj=0; jj<vdesc->num_attrs; jj++ )
00543 {
00544 assert( nc_inq_attname(id, ii, jj, adesc->mnem) == NC_NOERR);
00545 if( strcmp(adesc->mnem, reqattr[jj]) != 0 )
00546 {
00547 (void) printf("var %d attr %d mismatch %s != %s\n",
00548 ii, jj, adesc->mnem, reqattr[jj] );
00549 break;
00550 }
00551 }
00552
00553 if( nc_inq_att(id, ii, reqattr[0], &(adesc->type), &(adesc->len))
00554 != -1) {
00555 assert( adesc->type == NC_CHAR );
00556 assert( adesc->len == strlen(tvp->units) );
00557 assert( nc_get_att_text(id,ii,reqattr[0],buf)== NC_NOERR);
00558 buf[adesc->len] = 0;
00559 assert( strcmp(tvp->units, buf) == 0);
00560 }
00561
00562 if(
00563 nc_inq_att(id, ii, reqattr[1], &(adesc->type), &(adesc->len))
00564 != -1)
00565 {
00566 assert( adesc->type == NC_DOUBLE );
00567 assert( adesc->len == 1 );
00568 assert( nc_get_att_double(id, ii, reqattr[1], &got.dbl)== NC_NOERR);
00569 chkgot(adesc->type, got, tvp->validmin);
00570 }
00571
00572 if(
00573 nc_inq_att(id, ii, reqattr[2], &(adesc->type), &(adesc->len))
00574 != -1)
00575 {
00576 assert( adesc->type == NC_DOUBLE );
00577 assert( adesc->len == 1 );
00578 assert( nc_get_att_double(id, ii, reqattr[2], &got.dbl)== NC_NOERR);
00579 chkgot(adesc->type, got, tvp->validmax);
00580 }
00581
00582 if(
00583 nc_inq_att(id, ii, reqattr[3], &(adesc->type), &(adesc->len))
00584 != -1)
00585 {
00586 assert( adesc->type == NC_DOUBLE );
00587 assert( adesc->len ==1 );
00588 assert( nc_get_att_double(id, ii, reqattr[3], &got.dbl)== NC_NOERR);
00589 chkgot(adesc->type, got, tvp->scalemin);
00590 }
00591
00592 if(
00593 nc_inq_att(id, ii, reqattr[4], &(adesc->type), &(adesc->len))
00594 != -1)
00595 {
00596 assert( adesc->type == NC_DOUBLE );
00597 assert( adesc->len == 1 );
00598 assert( nc_get_att_double(id, ii, reqattr[4], &got.dbl)== NC_NOERR);
00599 chkgot(adesc->type, got, tvp->scalemax);
00600 }
00601
00602 if( nc_inq_att(id, ii, reqattr[5], &(adesc->type), &(adesc->len))== NC_NOERR)
00603 {
00604 assert( adesc->type == NC_CHAR );
00605 assert( adesc->len == strlen(tvp->fieldnam) );
00606 assert( nc_get_att_text(id,ii,reqattr[5],buf)== NC_NOERR);
00607 buf[adesc->len] = 0;
00608 assert( strcmp(tvp->fieldnam, buf) == 0);
00609 }
00610 }
00611
00612 (void) printf("fill_seq ");
00613 check_fill_seq(id);
00614 (void) printf("Done\n");
00615
00616 assert( nc_get_var1_double(id, Double_id, indices[0], &got.dbl)== NC_NOERR);
00617 (void) printf("got val = %f\n", got.dbl );
00618
00619 assert( nc_get_var1_double(id, Double_id, indices[1], &got.dbl)== NC_NOERR);
00620 (void) printf("got val = %f\n", got.dbl );
00621
00622 assert( nc_get_var1_float(id, Float_id, indices[2], &got.fl[0])== NC_NOERR);
00623 (void) printf("got val = %f\n", got.fl[0] );
00624
00625 assert( nc_get_var1_int(id, Long_id, indices[3], &got.in[0])== NC_NOERR);
00626 (void) printf("got val = %d\n", got.in[0] );
00627
00628 assert( nc_get_var1_short(id, Short_id, indices[4], &got.sh[0])== NC_NOERR);
00629 (void) printf("got val = %d\n", got.sh[0] );
00630
00631 assert( nc_get_var1_text(id, Char_id, indices[5], &got.by[0]) == NC_NOERR);
00632 (void) printf("got NC_CHAR val = %c (0x%02x) \n",
00633 got.by[0] , got.by[0]);
00634
00635 assert( nc_get_var1_text(id, Char_id, indices[6], &got.by[0]) == NC_NOERR);
00636 (void) printf("got NC_CHAR val = %c (0x%02x) \n",
00637 got.by[0], got.by[0] );
00638
00639 (void) memset(buf,0,sizeof(buf));
00640 assert( nc_get_vara_text(id, Char_id, s_start, s_edges, buf) == NC_NOERR);
00641 (void) printf("got NC_CHAR val = \"%s\"\n", buf);
00642
00643 assert( nc_get_var1_schar(id, Byte_id, indices[5],
00644 (signed char *)&got.by[0])== NC_NOERR);
00645 (void) printf("got val = %c (0x%02x) \n", got.by[0] , got.by[0]);
00646
00647 assert( nc_get_var1_schar(id, Byte_id, indices[6],
00648 (signed char *)&got.by[0])== NC_NOERR);
00649 (void) printf("got val = %c (0x%02x) \n", got.by[0], got.by[0] );
00650
00651 (void) memset(buf,0,sizeof(buf));
00652 assert( nc_get_vara_schar(id, Byte_id, s_start, s_edges,
00653 (signed char *)buf)== NC_NOERR );
00654 (void) printf("got val = \"%s\"\n", buf);
00655
00656 {
00657 double dbuf[NUM_RECS * SIZE_1 * SIZE_2];
00658 assert(nc_get_var_double(id, Float_id, dbuf) == NC_NOERR);
00659 (void) printf("got vals = %f ... %f\n", dbuf[0],
00660 dbuf[NUM_RECS * SIZE_1 * SIZE_2 -1] );
00661 }
00662
00663 ret = nc_close(id);
00664 (void) printf("re nc_close ret = %d\n", ret);
00665
00666 return 0;
00667 }