1/* This is part of the netCDF package.
2   Copyright 2005 University Corporation for Atmospheric Research/Unidata
3   See COPYRIGHT file for conditions of use.
4
5   Test netcdf-4 compound type feature.
6
7   $Id: tst_compounds.c,v 1.45 2010/05/25 13:53:03 ed Exp $
8*/
9
10#include <config.h>
11#include <stdlib.h>
12#include <nc_tests.h>
13#include "err_macros.h"
14
15#define FILE_NAME "tst_compounds.nc"
16#define SVC_REC "Service_Record"
17#define BATTLES_WITH_KLINGONS "Number_of_Battles_with_Klingons"
18#define DATES_WITH_ALIENS "Dates_with_Alien_Hotties"
19#define STARDATE "Stardate"
20#define RANK 1
21#define DIM_LEN 3
22#define SERVICE_RECORD "Kirk_Service_Record"
23
24int
25main(int argc, char **argv)
26{
27   printf("\n*** Testing netcdf-4 user defined type functions.\n");
28   printf("*** testing simple compound scalar variable create...");
29   {
30      int ncidtypeidvarid;
31      size_t nfields;
32      int ndimsnvarsnattsunlimdimid;
33      char name[NC_MAX_NAME + 1];
34      size_t size;
35      nc_type xtypefield_xtype;
36      int dimids[] = {0}, fieldid;
37      int field_ndimsfield_sizes[NC_TESTS_MAX_DIMS];
38      size_t offset;
39      struct s1
40      {
41     int i1;
42     int i2;
43      };
44      struct s1 datadata_in;
45
46      /* Create some phony data. */
47      data.i1 = 5;
48      data.i2 = 10;
49
50      /* Create a file with a compound type. Write a little data. */
51      if (nc_create(FILE_NAMENC_NETCDF4, &ncid)) ERR;
52      if (nc_def_compound(ncid, sizeof(struct s1), SVC_REC, &typeid)) ERR;
53      if (nc_inq_compound(ncidtypeidname, &size, &nfields)) ERR;
54      if (size != sizeof(struct s1) || strcmp(nameSVC_REC) || nfieldsERR;
55      if (nc_insert_compound(ncidtypeidBATTLES_WITH_KLINGONS,
56      NC_COMPOUND_OFFSET(struct s1i1), NC_INT)) ERR;
57      if (nc_insert_compound(ncidtypeidDATES_WITH_ALIENS,
58      NC_COMPOUND_OFFSET(struct s1i2), NC_INT)) ERR;
59      if (nc_def_var(ncidSERVICE_RECORDtypeid, 0, NULL, &varid)) ERR;
60      if (nc_put_var(ncidvarid, &data)) ERR;
61      if (nc_close(ncid)) ERR;
62
63      /* Open the file and take a peek. */
64      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
65      if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR;
66      if (ndims != 0 || nvars != 1 || natts != 0 || unlimdimid != -1) ERR;
67      if (nc_close(ncid)) ERR;
68
69      /* Reopen the file and take a more detailed look at the compound
70       * type. */
71      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
72      if (nc_inq_var(ncid, 0, name, &xtype, &ndimsdimids, &natts)) ERR;
73      if (strcmp(nameSERVICE_RECORD) || ndims != 0 || natts != 0) ERR;
74      if (nc_inq_compound(ncidxtypename, &size, &nfields)) ERR;
75      if (nfields != 2 || size != sizeof(struct s1) || strcmp(nameSVC_REC)) ERR;
76      if (nc_inq_compound_name(ncidxtypename)) ERR;
77      if (strcmp(nameSVC_REC)) ERR;
78      if (nc_inq_compound_size(ncidxtype, &size)) ERR;
79      if (size != sizeof(struct s1)) ERR;
80      if (nc_inq_compound_nfields(ncidxtype, &nfields)) ERR;
81      if (nfields != 2) ERR;
82      if (nc_inq_compound_field(ncidxtype, 0, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
83      if (field_ndimsERR;
84      if (strcmp(nameBATTLES_WITH_KLINGONS) || offset != 0 || (field_xtype != NC_INT || field_ndims != 0)) ERR;
85      if (nc_inq_compound_field(ncidxtype, 1, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
86      if (strcmp(nameDATES_WITH_ALIENS) || offset != 4 || field_xtype != NC_INTERR;
87      if (nc_inq_compound_fieldname(ncidxtype, 1, name)) ERR;
88      if (strcmp(nameDATES_WITH_ALIENS)) ERR;
89      if (nc_inq_compound_fieldindex(ncidxtypeBATTLES_WITH_KLINGONS, &fieldid)) ERR;
90      if (fieldid != 0) ERR;
91      if (nc_inq_compound_fieldoffset(ncidxtype, 1, &offset)) ERR;
92      if (offset != 4) ERR;
93      if (nc_inq_compound_fieldtype(ncidxtype, 1, &field_xtype)) ERR;
94      if (field_xtype != NC_INTERR;
95      if (nc_get_var(ncidvarid, &data_in)) ERR;
96      if (data.i1 != data_in.i1 || data.i2 != data_in.i2ERR;
97      if (nc_close(ncid)) ERR;
98   }
99   SUMMARIZE_ERR;
100   printf("*** testing simple compound variable create...");
101   {
102      int ncidtypeidvarid;
103      size_t nfields;
104      int dimid;
105      int ndimsnvarsnattsunlimdimid;
106      char name[NC_MAX_NAME + 1];
107      size_t size;
108      nc_type xtypefield_xtype;
109      int dimids[] = {0}, fieldid;
110      int field_ndimsfield_sizes[NC_TESTS_MAX_DIMS];
111      size_t offset;
112      int i;
113      struct s1
114      {
115     int i1;
116     int i2;
117      };
118      struct s1 data[DIM_LEN], data_in[DIM_LEN];
119      char *dummy;
120
121      /* REALLY initialize the data (even the gaps in the structs). This
122       * is only needed to pass valgrind. */
123      if (!(dummy = calloc(sizeof(struct s1), DIM_LEN)))
124  return NC_ENOMEM;
125      memcpy((void *)data, (void *)dummy, sizeof(struct s1) * DIM_LEN);
126      free(dummy);
127
128      /* Create some phony data. */
129      for (i = 0; i < DIM_LENi++)
130      {
131  data[i].i1 = 5;
132  data[i].i2 = 10;
133      }
134
135      /* Create a file with a compound type. Write a little data. */
136      if (nc_create(FILE_NAMENC_NETCDF4, &ncid)) ERR;
137      if (nc_def_compound(ncid, sizeof(struct s1), SVC_REC, &typeid)) ERR;
138      if (nc_inq_compound(ncidtypeidname, &size, &nfields)) ERR;
139      if (size != sizeof(struct s1) || strcmp(nameSVC_REC) || nfieldsERR;
140      if (nc_insert_compound(ncidtypeidBATTLES_WITH_KLINGONS,
141      NC_COMPOUND_OFFSET(struct s1i1), NC_INT)) ERR;
142      if (nc_insert_compound(ncidtypeidDATES_WITH_ALIENS,
143      NC_COMPOUND_OFFSET(struct s1i2), NC_INT)) ERR;
144      if (nc_def_dim(ncidSTARDATEDIM_LEN, &dimid)) ERR;
145      if (nc_def_var(ncidSERVICE_RECORDtypeid, 1, dimids, &varid)) ERR;
146      if (nc_put_var(ncidvariddata)) ERR;
147      if (nc_close(ncid)) ERR;
148
149      /* Open the file and take a peek. */
150      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
151      if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR;
152      if (ndims != 1 || nvars != 1 || natts != 0 || unlimdimid != -1) ERR;
153      if (nc_close(ncid)) ERR;
154
155      /* Reopen the file and take a more detailed look at the compound
156       * type. */
157      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
158      if (nc_inq_var(ncid, 0, name, &xtype, &ndimsdimids, &natts)) ERR;
159      if (strcmp(nameSERVICE_RECORD) || ndims != 1 || natts != 0 || dimids[0] != 0) ERR;
160      if (nc_inq_compound(ncidxtypename, &size, &nfields)) ERR;
161      if (nfields != 2 || size != sizeof(struct s1) || strcmp(nameSVC_REC)) ERR;
162      if (nc_inq_compound_name(ncidxtypename)) ERR;
163      if (strcmp(nameSVC_REC)) ERR;
164      if (nc_inq_compound_size(ncidxtype, &size)) ERR;
165      if (size != sizeof(struct s1)) ERR;
166      if (nc_inq_compound_nfields(ncidxtype, &nfields)) ERR;
167      if (nfields != 2) ERR;
168      if (nc_inq_compound_field(ncidxtype, 0, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
169      if (field_ndimsERR;
170      if (strcmp(nameBATTLES_WITH_KLINGONS) || offset != 0 || (field_xtype != NC_INT || field_ndims != 0)) ERR;
171      if (nc_inq_compound_field(ncidxtype, 1, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
172      if (strcmp(nameDATES_WITH_ALIENS) || offset != 4 || field_xtype != NC_INTERR;
173      if (nc_inq_compound_fieldname(ncidxtype, 1, name)) ERR;
174      if (strcmp(nameDATES_WITH_ALIENS)) ERR;
175      if (nc_inq_compound_fieldindex(ncidxtypeBATTLES_WITH_KLINGONS, &fieldid)) ERR;
176      if (fieldid != 0) ERR;
177      if (nc_inq_compound_fieldoffset(ncidxtype, 1, &offset)) ERR;
178      if (offset != 4) ERR;
179      if (nc_inq_compound_fieldtype(ncidxtype, 1, &field_xtype)) ERR;
180      if (field_xtype != NC_INTERR;
181      if (nc_get_var(ncidvariddata_in)) ERR;
182      for (i=0; i<DIM_LENi++)
183  if (data[i].i1 != data_in[i].i1 || data[i].i2 != data_in[i].i2ERR;
184
185      { /* Test if we can read/write with get_vars */
186#       define STRIDE_S 2
187#       define DIM_LEN_S ((1+DIM_LEN) / STRIDE_S)
188 size_t start[RANK] = {0};
189 size_t edges[RANK] = {2};
190 ptrdiff_t stride[RANK] = {2};
191        struct s1 datas[DIM_LEN_S];
192 memcpy(datas,data,sizeof(datas));
193 datas[0].i1 = 13; datas[0].i2 = 23;
194 datas[1].i1 = 111; datas[1].i2 = 222;
195 memset(data,0,sizeof(data));
196 if (nc_get_var(ncidvariddata)) ERR;
197        if (nc_put_vars(ncidvaridstartedgesstridedatas)) ERR;
198 memset(data,0,sizeof(data));
199 if (nc_get_var(ncidvariddata)) ERR;
200        for (i=0; i<DIM_LEN_Si++) { /* verify the write */
201   if(data[i*STRIDE_S].i1 != datas[i].i1 || data[i*STRIDE_S].i2 != datas[i].i2ERR;
202 }
203 /* Do a strided read */
204 memset(data,0,sizeof(data));
205        if (nc_get_vars(ncidvaridstartedgesstridedata)) ERR;
206        for (i=0; i<DIM_LEN_Si++) {
207   if(data[i].i1 != datas[i].i1 || data[i].i2 != datas[i].i2ERR;
208 }
209      }
210
211      if (nc_close(ncid)) ERR;
212   }
213   SUMMARIZE_ERR;
214   printf("*** testing REALLY simple compound variable create...");
215   {
216      int ncidtypeidvarid;
217      int ndimsnvarsnattsunlimdimid;
218      nc_type xtype;
219      size_t size_innfields_in;
220      char name_in[NC_MAX_NAME + 1];
221
222      /* Create a file with a compound type. Write a little data. */
223      if (nc_create(FILE_NAMENC_NETCDF4, &ncid)) ERR;
224      if (nc_def_compound(ncid, sizeof(int), SVC_REC, &typeid)) ERR;
225      if (nc_insert_compound(ncidtypeidBATTLES_WITH_KLINGONS, 0, NC_INT)) ERR;
226      if (nc_def_var(ncidSERVICE_RECORDtypeid, 0, NULL, &varid)) ERR;
227      if (nc_close(ncid)) ERR;
228
229      /* Open the file and take a peek. */
230      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
231      if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR;
232      if (ndims != 0 || nvars != 1 || natts != 0 || unlimdimid != -1) ERR;
233      if (nc_inq_vartype(ncid, 0, &xtype)) ERR;
234      if (nc_inq_compound(ncidxtypename_in, &size_in, &nfields_in)) ERR;
235      if (strcmp(name_inSVC_REC) || size_in != sizeof(int) || nfields_in != 1) ERR;
236      if (nc_close(ncid)) ERR;
237   }
238   SUMMARIZE_ERR;
239   printf("*** testing simple compound attribute create...");
240   {
241      int ncidtypeid;
242      size_t nfields;
243      int ndimsnvarsnattsunlimdimid;
244      char name[NC_MAX_NAME + 1];
245      size_t sizelen;
246      nc_type xtypefield_xtype;
247      int fieldid;
248      int field_ndimsfield_sizes[NC_TESTS_MAX_DIMS];
249      size_t offset;
250      int i;
251      struct s1
252      {
253     int i1;
254     int i2;
255      };
256      struct s1 data[DIM_LEN], data_in[DIM_LEN];
257      char *dummy;
258
259      /* REALLY initialize the data (even the gaps in the structs). This
260       * is only needed to pass valgrind. */
261      if (!(dummy = calloc(sizeof(struct s1), DIM_LEN)))
262  return NC_ENOMEM;
263      memcpy((void *)data, (void *)dummy, sizeof(struct s1) * DIM_LEN);
264      free(dummy);
265
266      /* Create some phony data. */
267      for (i=0; i<DIM_LENi++)
268      {
269  data[i].i1 = 5;
270  data[i].i2 = 10;
271      }
272
273      /* Create a file with a global attribute of compound type. */
274      if (nc_create(FILE_NAMENC_NETCDF4, &ncid)) ERR;
275      if (nc_def_compound(ncid, sizeof(struct s1), SVC_REC, &typeid)) ERR;
276      if (nc_insert_compound(ncidtypeidBATTLES_WITH_KLINGONS,
277      NC_COMPOUND_OFFSET(struct s1i1), NC_INT)) ERR;
278      if (nc_insert_compound(ncidtypeidDATES_WITH_ALIENS,
279      NC_COMPOUND_OFFSET(struct s1i2), NC_INT)) ERR;
280      if (nc_put_att(ncidNC_GLOBALSERVICE_RECORDtypeid, 3, data)) ERR;
281      if (nc_close(ncid)) ERR;
282
283      /* Open the file and take a peek. */
284      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
285      if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR;
286      if (ndims != 0 || nvars != 0 || natts != 1 || unlimdimid != -1) ERR;
287      if (nc_close(ncid)) ERR;
288
289      /* Reopen the file and take a more detailed look at the compound
290       * type. */
291      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
292      if (nc_get_att(ncidNC_GLOBALSERVICE_RECORDdata_in)) ERR;
293      for (i = 0; i < DIM_LENi++)
294  if (data[i].i1 != data_in[i].i1 || data[i].i2 != data_in[i].i2ERR;;
295      if (nc_inq_att(ncidNC_GLOBALSERVICE_RECORD, &xtype, &len)) ERR;
296      if (len != 3) ERR;
297      if (nc_inq_compound(ncidxtypename, &size, &nfields)) ERR;
298      if (nfields != 2 || size != 8 || strcmp(nameSVC_REC)) ERR;
299      if (nc_inq_compound_nfields(ncidxtype, &nfields)) ERR;
300      if (nfields != 2) ERR;
301      if (nc_inq_compound_field(ncidxtype, 0, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
302      if (strcmp(nameBATTLES_WITH_KLINGONS) || offset != 0 || field_xtype != NC_INTERR;
303      if (nc_inq_compound_field(ncidxtype, 1, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
304      if (strcmp(nameDATES_WITH_ALIENS) || offset != 4 || field_xtype != NC_INTERR;
305      if (nc_inq_compound_fieldindex(ncidxtypeBATTLES_WITH_KLINGONS, &fieldid)) ERR;
306      if (fieldid != 0) ERR;
307      if (nc_inq_compound_fieldoffset(ncidxtype, 1, &offset)) ERR;
308      if (offset != 4) ERR;
309      if (nc_inq_compound_fieldtype(ncidxtype, 1, &field_xtype)) ERR;
310      if (field_xtype != NC_INTERR;
311      if (nc_close(ncid)) ERR;
312   }
313
314   SUMMARIZE_ERR;
315   printf("*** testing compound variable with new atomic types...");
316   {
317      int ncidtypeiddimidvarid;
318      size_t nfields;
319      int ndimsnatts;
320      char name[NC_MAX_NAME + 1];
321      size_t size;
322      nc_type xtypefield_xtype;
323      int dimids[] = {0};
324      int field_ndimsfield_sizes[NC_TESTS_MAX_DIMS];
325      size_t offset;
326      int i;
327
328      /* StarFleet Medical Record. */
329      struct sf_med_rec
330      {
331     unsigned char num_heads;
332     unsigned short num_arms;
333     unsigned int num_toes;
334     long long ago; /* in a galaxy far far away... */
335     unsigned long long num_hairs;
336      };
337      struct sf_med_rec med_data_out[DIM_LEN], med_data_in[DIM_LEN];
338      char *dummy;
339
340      /* REALLY initialize the data (even the gaps in the structs). This
341       * is only needed to pass valgrind. */
342      if (!(dummy = calloc(sizeof(struct sf_med_rec), DIM_LEN)))
343  return NC_ENOMEM;
344      memcpy((void *)med_data_out, (void *)dummy, sizeof(struct sf_med_rec) * DIM_LEN);
345      free(dummy);
346
347      /* Create some phony data. */
348      for (i=0; i<DIM_LENi++)
349      {
350  /* medical data */
351  med_data_out[i].num_heads = 254;
352  med_data_out[i].num_arms = NC_FILL_USHORT - 1;
353  med_data_out[i].num_toes = NC_FILL_UINT - 1;
354  med_data_out[i].ago = NC_FILL_INT64 + 1;
355  med_data_out[i].num_hairs = NC_FILL_UINT64 - 1;
356      }
357
358      /* Create a file with a compound type. Write a little data. */
359      if (nc_create(FILE_NAMENC_NETCDF4, &ncid)) ERR;
360      if (nc_def_compound(ncid, sizeof(struct sf_med_rec), "SFMedRec", &typeid)) ERR;
361      if (nc_insert_compound(ncidtypeid, "num_heads",
362      NC_COMPOUND_OFFSET(struct sf_med_recnum_heads), NC_UBYTE)) ERR;
363      if (nc_insert_compound(ncidtypeid, "num_arms",
364      NC_COMPOUND_OFFSET(struct sf_med_recnum_arms), NC_USHORT)) ERR;
365      if (nc_insert_compound(ncidtypeid, "num_toes",
366      NC_COMPOUND_OFFSET(struct sf_med_recnum_toes), NC_UINT)) ERR;
367      if (nc_insert_compound(ncidtypeid, "ago",
368      NC_COMPOUND_OFFSET(struct sf_med_recago), NC_INT64)) ERR;
369      if (nc_insert_compound(ncidtypeid, "num_hairs",
370      NC_COMPOUND_OFFSET(struct sf_med_recnum_hairs), NC_UINT64)) ERR;
371      if (nc_def_dim(ncidSTARDATEDIM_LEN, &dimid)) ERR;
372      if (nc_def_var(ncid, "starbase_13", typeid, 1, dimids, &varid)) ERR;
373      if (nc_put_var(ncidvaridmed_data_out)) ERR;
374      if (nc_close(ncid)) ERR;
375
376      /* Open the file and take a look. */
377      {
378  if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
379  if (nc_inq_var(ncid, 0, name, &xtype, &ndimsdimids, &natts)) ERR;
380  if (strcmp(name, "starbase_13") || ndims != 1 || natts != 0 || dimids[0] != 0) ERR;
381  if (nc_inq_compound(ncidxtypename, &size, &nfields)) ERR;
382  if (nfields != 5 || size != sizeof(struct sf_med_rec) || strcmp(name, "SFMedRec")) ERR;
383  if (nc_inq_compound_field(ncidxtype, 0, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
384  if (strcmp(name, "num_heads") || offset != 0 || field_xtype != NC_UBYTEERR;
385  if (nc_inq_compound_field(ncidxtype, 1, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
386  if (strcmp(name, "num_arms") || offset != NC_COMPOUND_OFFSET(struct sf_med_recnum_arms) ||
387      field_xtype != NC_USHORTERR;
388  if (nc_inq_compound_field(ncidxtype, 2, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
389  if (strcmp(name, "num_toes") || offset != NC_COMPOUND_OFFSET(struct sf_med_recnum_toes) ||
390      field_xtype != NC_UINTERR;
391  if (nc_inq_compound_field(ncidxtype, 3, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
392  if (strcmp(name, "ago") || offset != NC_COMPOUND_OFFSET(struct sf_med_recago) ||
393      field_xtype != NC_INT64ERR;
394  if (nc_inq_compound_field(ncidxtype, 4, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
395  if (strcmp(name, "num_hairs") || offset != NC_COMPOUND_OFFSET(struct sf_med_recnum_hairs) ||
396      field_xtype != NC_UINT64ERR;
397  if (nc_get_var(ncidvaridmed_data_in)) ERR;
398  for (i=0; i<DIM_LENi++)
399     if (med_data_in[i].num_heads != med_data_out[i].num_heads ||
400 med_data_in[i].num_arms != med_data_out[i].num_arms ||
401 med_data_in[i].num_toes != med_data_out[i].num_toes ||
402 med_data_in[i].ago != med_data_out[i].ago ||
403 med_data_in[i].num_hairs != med_data_out[i].num_hairsERR;
404  if (nc_close(ncid)) ERR;
405      }
406   }
407
408   SUMMARIZE_ERR;
409   printf("*** testing compound variable containing an array of ints...");
410   {
411#define NUM_DIMENSIONS 7
412
413      int ncidtypeidvarid;
414      size_t nfields;
415      int dimid;
416      int ndimsnatts;
417      char name[NC_MAX_NAME + 1];
418      size_t size;
419      nc_type xtype;
420      int dimids[] = {0};
421      int field_ndimsfield_sizes[NC_TESTS_MAX_DIMS];
422      size_t offset;
423      nc_type field_typeid;
424      int dim_sizes[] = {NUM_DIMENSIONS};
425      int ij;
426
427      /* Since some aliens exists in different, or more than one,
428       * dimensions, StarFleet keeps track of the dimensional
429       * abilities of everyone on 7 dimensions. */
430      struct dim_rec
431      {
432     int starfleet_id;
433     int abilities[NUM_DIMENSIONS];
434      };
435      struct dim_rec dim_data_out[DIM_LEN], dim_data_in[DIM_LEN];
436      char *dummy;
437
438      /* REALLY initialize the data (even the gaps in the structs). This
439       * is only needed to pass valgrind. */
440      if (!(dummy = calloc(sizeof(struct dim_rec), DIM_LEN)))
441  return NC_ENOMEM;
442      memcpy((void *)dim_data_out, (void *)dummy, sizeof(struct dim_rec) * DIM_LEN);
443      free(dummy);
444
445      /* Create some phony data. */
446      for (i=0; i<DIM_LENi++)
447      {
448  dim_data_out[i].starfleet_id = i;
449  for (j = 0; j < NUM_DIMENSIONSj++)
450     dim_data_out[i].abilities[j] = j;
451      }
452
453
454      /* Create a file with a compound type which contains an array of
455       * int. Write a little data. */
456      if (nc_create(FILE_NAMENC_NETCDF4, &ncid)) ERR;
457      if (nc_def_compound(ncid, sizeof(struct dim_rec), "SFDimRec", &typeid)) ERR;
458      if (nc_insert_compound(ncidtypeid, "starfleet_id",
459      NC_COMPOUND_OFFSET(struct dim_recstarfleet_id), NC_INT)) ERR;
460      if (nc_insert_array_compound(ncidtypeid, "abilities",
461      NC_COMPOUND_OFFSET(struct dim_recabilities), NC_INT, 1, dim_sizes)) ERR;
462      if (nc_inq_compound_field(ncidtypeid, 1, name, &offset, &field_typeid,
463 &field_ndimsfield_sizes)) ERR;
464      if (strcmp(name, "abilities") || offset != 4 || field_typeid != NC_INT ||
465   field_ndims != 1 || field_sizes[0] != dim_sizes[0]) ERR;
466      if (nc_def_dim(ncidSTARDATEDIM_LEN, &dimid)) ERR;
467      if (nc_def_var(ncid, "dimension_data", typeid, 1, dimids, &varid)) ERR;
468      if (nc_put_var(ncidvariddim_data_out)) ERR;
469      if (nc_close(ncid)) ERR;
470
471      /* Open the file and take a look. */
472      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
473      if (nc_inq_var(ncid, 0, name, &xtype, &ndimsdimids, &natts)) ERR;
474      if (strcmp(name, "dimension_data") || ndims != 1 || natts != 0 || dimids[0] != 0) ERR;
475      if (nc_inq_compound(ncidxtypename, &size, &nfields)) ERR;
476      if (nfields != 2 || size != sizeof(struct dim_rec) || strcmp(name, "SFDimRec")) ERR;
477      if (nc_inq_compound_field(ncidxtype, 1, name, &offset, &field_typeid,
478 &field_ndimsfield_sizes)) ERR;
479      if (strcmp(name, "abilities") || offset != 4 || field_typeid != NC_INT ||
480   field_ndims != 1 || field_sizes[0] != NUM_DIMENSIONSERR;
481      if (nc_get_var(ncidvariddim_data_in)) ERR;
482      for (i=0; i<DIM_LENi++)
483      {
484  if (dim_data_in[i].starfleet_id != dim_data_out[i].starfleet_idERR;
485  for (j = 0; j < NUM_DIMENSIONSj++)
486     if (dim_data_in[i].abilities[j] != dim_data_out[i].abilities[j]) ERR;
487      }
488      if (nc_close(ncid)) ERR;
489   }
490
491   SUMMARIZE_ERR;
492   printf("*** testing compound var containing compound type...");
493   {
494      int ncid;
495      size_t nfields;
496      char name[NC_MAX_NAME + 1];
497      size_t sizelen;
498      nc_type xtypefield_xtype;
499      int field_ndimsfield_sizes[NC_TESTS_MAX_DIMS];
500      size_t offset;
501      nc_type svc_recidhr_recid;
502      int dim_sizes[] = {NC_MAX_NAME + 1};
503      int i;
504
505      /* The following structs are written and read as compound types by
506       * the tests below. */
507      struct s1
508      {
509     int i1;
510     int i2;
511      };
512      struct s1 data[DIM_LEN];
513
514      /* StarFleet Human Resources Department has data records for all
515       * employees. */
516      struct hr_rec
517      {
518     int starfleet_id;
519     struct s1 svc_rec;
520     char name[NC_MAX_NAME + 1];
521     float max_tempmin_temp; /* temperature range */
522     double percent_transporter_errosion;
523      };
524      struct hr_rec hr_data_out[DIM_LEN], hr_data_in[DIM_LEN];
525      char *dummy;
526
527      /* REALLY initialize the data (even the gaps in the structs). This
528       * is only needed to pass valgrind. */
529      if (!(dummy = calloc(sizeof(struct hr_rec), DIM_LEN)))
530  return NC_ENOMEM;
531      memcpy((void *)hr_data_out, (void *)dummy, sizeof(struct hr_rec) * DIM_LEN);
532      free(dummy);
533
534      /* Create some phony data. */
535      for (i=0; i<DIM_LENi++)
536      {
537  data[i].i1 = 5;
538  data[i].i2 = 10;
539  /* hr data */
540  hr_data_out[i].starfleet_id = i;
541  hr_data_out[i].svc_rec = data[i];
542  if (sprintf(hr_data_out[i].name, "alien_%d", i) < 0) ERR;
543  hr_data_out[i].max_temp = 99.99;
544  hr_data_out[i].min_temp = -9.99;
545  hr_data_out[i].percent_transporter_errosion = .030303;
546      }
547
548      /* Create a file with a nested compound type attribute and variable. */
549      if (nc_create(FILE_NAMENC_NETCDF4, &ncid)) ERR;
550
551      /* Define the inner type first. */
552      if (nc_def_compound(ncid, sizeof(struct s1), SVC_REC, &svc_recid)) ERR;
553      if (nc_insert_compound(ncidsvc_recidBATTLES_WITH_KLINGONS,
554      NC_COMPOUND_OFFSET(struct s1i1), NC_INT)) ERR;
555      if (nc_insert_compound(ncidsvc_recidDATES_WITH_ALIENS,
556      NC_COMPOUND_OFFSET(struct s1i2), NC_INT)) ERR;
557
558      /* Now define the containing type. */
559      if (nc_def_compound(ncid, sizeof(struct hr_rec), "SF_HR_Record", &hr_recid)) ERR;
560      if (nc_insert_compound(ncidhr_recid, "StarFleet_ID",
561      NC_COMPOUND_OFFSET(struct hr_recstarfleet_id), NC_INT)) ERR;
562      if (nc_insert_compound(ncidhr_recid, "Service_Record",
563      NC_COMPOUND_OFFSET(struct hr_recsvc_rec), svc_recid)) ERR;
564      if (nc_insert_array_compound(ncidhr_recid, "Name",
565    NC_COMPOUND_OFFSET(struct hr_recname), NC_CHAR, 1, dim_sizes)) ERR;
566      if (nc_insert_compound(ncidhr_recid, "Max_Temp",
567      NC_COMPOUND_OFFSET(struct hr_recmax_temp), NC_FLOAT)) ERR;
568      if (nc_insert_compound(ncidhr_recid, "Min_Temp",
569      NC_COMPOUND_OFFSET(struct hr_recmin_temp), NC_FLOAT)) ERR;
570      if (nc_insert_compound(ncidhr_recid, "Percent_Transporter_Erosian",
571      NC_COMPOUND_OFFSET(struct hr_recpercent_transporter_errosion),
572      NC_DOUBLE)) ERR;
573
574      /* Write it as an attribute. */
575      if (nc_put_att(ncidNC_GLOBAL, "HR_Records", hr_recidDIM_LEN,
576      hr_data_out)) ERR;
577      if (nc_close(ncid)) ERR;
578
579      /* Read the att and check values. */
580      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
581      if (nc_get_att(ncidNC_GLOBAL, "HR_Records", hr_data_in)) ERR;
582      for (i=0; i<DIM_LENi++)
583      {
584  if (hr_data_in[i].starfleet_id != hr_data_out[i].starfleet_id ||
585      hr_data_in[i].svc_rec.i1 != hr_data_out[i].svc_rec.i1 ||
586      hr_data_in[i].svc_rec.i2 != hr_data_out[i].svc_rec.i2 ||
587      strcmp(hr_data_in[i].namehr_data_out[i].name) ||
588      hr_data_in[i].max_temp != hr_data_out[i].max_temp ||
589      hr_data_in[i].min_temp != hr_data_out[i].min_temp ||
590      hr_data_in[i].percent_transporter_errosion !=
591      hr_data_out[i].percent_transporter_errosionERR;
592      }
593
594      /* Use the inq functions to learn about nested compound type. */
595      if (nc_inq_att(ncidNC_GLOBAL, "HR_Records", &xtype, &len)) ERR;
596      if (len != DIM_LENERR;
597      if (nc_inq_compound(ncidxtypename, &size, &nfields)) ERR;
598      if (nfields != 6 || size != sizeof(struct hr_rec) || strcmp(name, "SF_HR_Record")) ERR;
599      if (nc_inq_compound_field(ncidxtype, 0, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
600      if (strcmp(name, "StarFleet_ID") || offset != 0 || field_xtype != NC_INTERR;
601      if (nc_inq_compound_field(ncidxtype, 1, name, &offset, &field_xtype, &field_ndimsfield_sizes)) ERR;
602      if (strcmp(name, "Service_Record") || offset != NC_COMPOUND_OFFSET(struct hr_recsvc_rec)) ERR;
603      /* Check the internal compound type. */
604
605      /* Finish checking the containing compound type. */
606      if (nc_close(ncid)) ERR;
607   }
608
609   SUMMARIZE_ERR;
610   printf("*** creating compound test file...");
611
612   {
613#define TYPE6_NAME "obs_t"
614#define DIM6_NAME "n"
615#define DIM6_LEN 3
616#define VAR6_NAME "obs"
617#define VAR6_RANK 1
618#define ATT6_NAME "_FillValue"
619#define ATT6_LEN  1
620      int ncid;
621      int dimidvarid;
622      nc_type typeid;
623      char name_in[NC_MAX_NAME+1];
624      int i;
625
626      int var_dims[VAR6_RANK];
627
628      typedef struct obs_t {
629     char day ;
630     short elev;
631     int count;
632     float relhum;
633     double time;
634      } obs_t ;
635      obs_t obsdata[DIM6_LEN];
636      char *dummy;
637
638      obs_t missing_val;
639      obs_t val_in;
640      size_t size_in;
641      size_t nfields_in;
642      nc_type class_in;
643      int ntypes;
644
645      /* REALLY initialize the data (even the gaps in the structs). This
646       * is only needed to pass valgrind. */
647      if (!(dummy = calloc(sizeof(struct obs_t), DIM6_LEN)))
648  return NC_ENOMEM;
649      memcpy((void *)obsdata, (void *)dummy, sizeof(struct obs_t) * DIM6_LEN);
650      memcpy((void *)&missing_val, (void *)dummy, sizeof(struct obs_t));
651      free(dummy);
652
653      /* Initialize data. */
654      for (i = 0; i < DIM6_LENi++)
655      {
656  obsdata[i].day = 15 * i + 1;
657  obsdata[i].elev = 2 * i + 1;
658  obsdata[i].count = 2 * i + 1;
659  obsdata[i].relhum = 2.0 * i + 1;
660  obsdata[i].time = 2.0 * i + 1;
661      }
662      missing_val.day = 99;
663      missing_val.elev = 99;
664      missing_val.count = 99;
665      missing_val.relhum = 99.;
666      missing_val.time = 99.;
667
668      if (nc_create(FILE_NAMENC_CLOBBER | NC_NETCDF4, &ncid)) ERR;
669
670      /* Create a compound type. */
671      if (nc_def_compound(ncid, sizeof(obs_t), TYPE6_NAME, &typeid)) ERR;
672      if (nc_insert_compound(ncidtypeid, "day", NC_COMPOUND_OFFSET(struct obs_tday),
673      NC_BYTE)) ERR;
674      if (nc_insert_compound(ncidtypeid, "elev", NC_COMPOUND_OFFSET(struct obs_telev),
675      NC_SHORT)) ERR;
676      if (nc_insert_compound(ncidtypeid, "count", NC_COMPOUND_OFFSET(struct obs_tcount),
677      NC_INT)) ERR;
678      if (nc_insert_compound(ncidtypeid, "relhum", NC_COMPOUND_OFFSET(struct obs_trelhum),
679      NC_FLOAT)) ERR;
680      if (nc_insert_compound(ncidtypeid, "time", NC_COMPOUND_OFFSET(struct obs_t, time),
681      NC_DOUBLE)) ERR;
682
683      /* Declare a dimension for number of obs */
684      if (nc_def_dim(ncidDIM6_NAMEDIM6_LEN, &dimid)) ERR;
685
686      /* Declare a variable of the compound type */
687      var_dims[0] = dimid;
688      if (nc_def_var(ncidVAR6_NAMEtypeidVAR6_RANKvar_dims, &varid)) ERR;
689
690      /* Create and write a variable attribute of the compound type */
691      if (nc_put_att(ncidvaridATT6_NAMEtypeidATT6_LEN, (void *) &missing_val)) ERR;
692      if (nc_enddef(ncid)) ERR;
693
694      /* Store data, writing all values in one call */
695      if(nc_put_var(ncidvaridobsdata)) ERR;
696
697      /* Write the file. */
698      if (nc_close(ncid)) ERR;
699
700      /* Check it out. */
701
702      /* Reopen the file. */
703      if (nc_open(FILE_NAMENC_NOWRITE, &ncid)) ERR;
704
705      if (nc_inq_typeids(ncid, &ntypes, &typeid)) ERR;
706      if (ntypes != 1) ERR;
707
708      /* Get info with the generic inquire for user-defined types */
709      if (nc_inq_user_type(ncidtypeidname_inNULLNULL,
710    NULL, &class_in)) ERR;
711      if (strcmp(name_inTYPE6_NAME) ||
712   class_in != NC_COMPOUNDERR;
713
714      /* Get the same info with the compound-specific inquire function */
715      if (nc_inq_compound(ncidtypeidname_in, &size_in, &nfields_in)) ERR;
716      if (strcmp(name_inTYPE6_NAME) ||
717   size_in != sizeof(obs_t) ||
718   nfields_in != 5) ERR;
719
720      if (nc_inq_varid(ncidVAR6_NAME, &varid)) ERR;
721
722      /* Read in attribute value and check it */
723      if (nc_get_att(ncidvaridATT6_NAME, &val_in)) ERR;
724      if (val_in.day != missing_val.day ||
725   val_in.elev != missing_val.elev ||
726   val_in.count != missing_val.count ||
727   val_in.relhum != missing_val.relhumERR;
728
729      /* Read in each value and check */
730      for (i = 0; i < DIM6_LENi++) {
731  size_t index[VAR6_RANK];
732  index[0] = i;
733  if (nc_get_var1(ncidvaridindex, (void *) &val_in)) ERR;
734  /* TODO: check values */
735  if (val_in.day != obsdata[i].dayERR;
736  if (val_in.elev != obsdata[i].elevERR;
737  if (val_in.count != obsdata[i].countERR;
738  if (val_in.relhum != obsdata[i].relhumERR;
739  if (val_in.time != obsdata[i].time) ERR;
740      }
741
742      if (nc_close(ncid)) ERR;
743
744   }
745
746   SUMMARIZE_ERR;
747   printf("*** Now opening the ref file for this...");
748   {
749#define REF_FILE_NAME "ref_tst_compounds.nc"
750      int ncid;
751      int varid;
752      nc_type typeid;
753      char name_in[NC_MAX_NAME+1];
754      int i;
755
756      typedef struct obs_t {
757     char day ;
758     short elev;
759     int count;
760     float relhum;
761     double time;
762      } obs_t ;
763
764      obs_t obsdata[DIM6_LEN] = {
765  {15, 2, 1, 0.5, 3600.01},
766  {-99, -99, -99, -99.0f, -99.0},
767  {20, 6, 3, 0.75, 5000.01}
768      };
769      obs_t missing_val = {-99, -99, -99, -99, -99};
770      obs_t val_in;
771      size_t size_in;
772      size_t nfields_in;
773      nc_type class_in;
774      int ntypes;
775      char file_in[NC_MAX_NAME * 2];
776
777      if (getenv("srcdir"))
778      {
779  strcpy(file_in, getenv("srcdir"));
780  strcat(file_in, "/");
781  strcat(file_inREF_FILE_NAME);
782      }
783      else
784  strcpy(file_inREF_FILE_NAME);
785
786      /* Reopen the file. */
787      if (nc_open(file_inNC_NOWRITE, &ncid)) ERR;
788
789      if (nc_inq_typeids(ncid, &ntypes, &typeid)) ERR;
790      if (ntypes != 1) ERR;
791
792      /* Get info with the generic inquire for user-defined types */
793      if (nc_inq_user_type(ncidtypeidname_inNULLNULL,
794    NULL, &class_in)) ERR;
795      if (strcmp(name_inTYPE6_NAME) ||
796   class_in != NC_COMPOUNDERR;
797
798      /* Get the same info with the compound-specific inquire function */
799      if (nc_inq_compound(ncidtypeidname_in, &size_in, &nfields_in)) ERR;
800      if (strcmp(name_inTYPE6_NAME) || size_in != sizeof(obs_t) ||
801   nfields_in != 5) ERR;
802
803      if (nc_inq_varid(ncidVAR6_NAME, &varid)) ERR;
804
805      /* Read in attribute value and check it */
806      if (nc_get_att(ncidvaridATT6_NAME, &val_in)) ERR;
807      if (val_in.day != missing_val.day ||
808   val_in.elev != missing_val.elev ||
809   val_in.count != missing_val.count ||
810   val_in.relhum != missing_val.relhumERR;
811
812      /* Read in each value and check */
813      for (i = 0; i < DIM6_LENi++) {
814  size_t index[VAR6_RANK];
815  index[0] = i;
816  if (nc_get_var1(ncidvaridindex, (void *) &val_in)) ERR;
817  /* TODO: check values */
818  if (val_in.day != obsdata[i].dayERR;
819  if (val_in.elev != obsdata[i].elevERR;
820  if (val_in.count != obsdata[i].countERR;
821  if (val_in.relhum != obsdata[i].relhumERR;
822  if (val_in.time != obsdata[i].time) ERR;
823      }
824
825      if (nc_close(ncid)) ERR;
826   }
827
828   SUMMARIZE_ERR;
829   printf("*** testing compound var containing char array...");
830   {
831#define DIM1_LEN 1
832      int ncid;
833      size_t len;
834      nc_type xtype;
835      nc_type hr_recid;
836      int dim_sizes[] = {NC_MAX_NAME + 1};
837      int i;
838
839      /* StarFleet Human Resources Department has data records for all
840       * employees. */
841      struct hr_rec
842      {
843     char name[NC_MAX_NAME + 1];
844     float max_temp;
845      };
846      struct hr_rec hr_data_out[DIM1_LEN], hr_data_in[DIM1_LEN];
847      char *dummy;
848
849      /* REALLY initialize the data (even the gaps in the structs). This
850       * is only needed to pass valgrind. */
851      if (!(dummy = calloc(sizeof(struct hr_rec), DIM1_LEN)))
852  return NC_ENOMEM;
853      memcpy((void *)hr_data_out, (void *)dummy, sizeof(struct hr_rec) * DIM1_LEN);
854      free(dummy);
855
856      /* Create some phony data. */
857      for (i = 0; i < DIM1_LENi++)
858      {
859  if (sprintf(hr_data_out[i].name, "alien_%d", i) < 0) ERR;
860  hr_data_out[i].max_temp = 99.99;
861      }
862
863      /* Create a file with a nested compound type attribute and variable. */
864      if (nc_create(FILE_NAMENC_NETCDF4, &ncid)) ERR;
865
866      /* Now define the compound type. */
867      /*printf("sizeof(struct hr_rec)=%d\n", sizeof(struct hr_rec));*/
868      if (nc_def_compound(ncid, sizeof(struct hr_rec), "SF_HR_Record", &hr_recid)) ERR;
869      if (nc_insert_array_compound(ncidhr_recid, "Name",
870    NC_COMPOUND_OFFSET(struct hr_recname), NC_CHAR, 1, dim_sizes)) ERR;
871      if (nc_insert_compound(ncidhr_recid, "Max_Temp",
872      NC_COMPOUND_OFFSET(struct hr_recmax_temp), NC_FLOAT)) ERR;
873
874      /* Write it as an attribute. */
875      if (nc_put_att(ncidNC_GLOBAL, "HR_Records", hr_recidDIM1_LENhr_data_out)) ERR;
876      if (nc_close(ncid)) ERR;
877
878      /* Read the att and check values. */
879      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
880      if (nc_get_att(ncidNC_GLOBAL, "HR_Records", hr_data_in)) ERR;
881      for (i=0; i<DIM1_LENi++)
882  if (strcmp(hr_data_in[i].namehr_data_out[i].name) ||
883      hr_data_in[i].max_temp != hr_data_out[i].max_tempERR;
884
885      /* Use the inq functions to learn about the compound type. */
886      if (nc_inq_att(ncidNC_GLOBAL, "HR_Records", &xtype, &len)) ERR;
887      if (len != DIM1_LENERR;
888
889      /* Finish checking the containing compound type. */
890      if (nc_close(ncid)) ERR;
891   }
892
893   SUMMARIZE_ERR;
894   printf("*** testing compound var containing byte array...");
895   {
896#define DIM1_LEN 1
897#define ARRAY_LEN (NC_MAX_NAME + 1)
898      int ncid;
899      size_t len;
900      nc_type xtype;
901      nc_type hr_recid;
902      int dim_sizes[] = {ARRAY_LEN};
903      int ij;
904      char *dummy;
905      /* StarFleet Human Resources Department has data records for all
906       * employees. */
907      struct hr_rec
908      {
909     char name[ARRAY_LEN];
910     float max_temp;
911      };
912      struct hr_rec hr_data_out[DIM1_LEN], hr_data_in[DIM1_LEN];
913
914      /* REALLY initialize the data (even the gaps in the structs). This
915       * is only needed to pass valgrind. */
916      if (!(dummy = calloc(sizeof(struct hr_rec), DIM1_LEN)))
917  return NC_ENOMEM;
918      memcpy((void *)hr_data_out, (void *)dummy, sizeof(struct hr_rec) * DIM1_LEN);
919      free(dummy);
920
921      /* Create some phony data. */
922      for (i = 0; i < DIM1_LENi++)
923      {
924  hr_data_out[i].max_temp = 99.99;
925  for (j = 0; j < ARRAY_LENj++)
926     hr_data_out[i].name[j] = j;
927      }
928
929      /* Create a file with a nested compound type attribute and variable. */
930      if (nc_create(FILE_NAMENC_NETCDF4, &ncid)) ERR;
931
932      /* Now define the compound type. */
933      /*printf("sizeof(struct hr_rec)=%d\n", sizeof(struct hr_rec));*/
934      if (nc_def_compound(ncid, sizeof(struct hr_rec), "SF_HR_Record", &hr_recid)) ERR;
935      if (nc_insert_array_compound(ncidhr_recid, "Name",
936    NC_COMPOUND_OFFSET(struct hr_recname), NC_UBYTE, 1, dim_sizes)) ERR;
937      if (nc_insert_compound(ncidhr_recid, "Max_Temp",
938      NC_COMPOUND_OFFSET(struct hr_recmax_temp), NC_FLOAT)) ERR;
939
940      /* Write it as an attribute. */
941      if (nc_put_att(ncidNC_GLOBAL, "HR_Records", hr_recidDIM1_LENhr_data_out)) ERR;
942      if (nc_close(ncid)) ERR;
943
944      /* Read the att and check values. */
945      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
946      if (nc_get_att(ncidNC_GLOBAL, "HR_Records", hr_data_in)) ERR;
947      for (i = 0; i < DIM1_LENi++)
948      {
949  if (hr_data_in[i].max_temp != hr_data_out[i].max_tempERR;
950  for (j = 0; j < ARRAY_LENj++)
951     if (hr_data_in[i].name[j] != hr_data_out[i].name[j]) ERR;
952      }
953
954      /* Use the inq functions to learn about the compound type. */
955      if (nc_inq_att(ncidNC_GLOBAL, "HR_Records", &xtype, &len)) ERR;
956      if (len != DIM1_LENERR;
957
958      /* Finish checking the containing compound type. */
959      if (nc_close(ncid)) ERR;
960   }
961   SUMMARIZE_ERR;
962   printf("*** testing with user-contributed code...");
963   {
964#define DATA_LEN 1
965      int ncidtypeidvariddimid;
966      int dimids[] = {0};
967      struct s1
968      {
969  short i;
970  long long j;
971      };
972      struct s1 data_out[DATA_LEN], data_in[DATA_LEN];
973      int idx;
974      char *dummy;
975
976      /* REALLY initialize the data (even the gaps in the structs). This
977       * is only needed to pass valgrind. */
978      if (!(dummy = calloc(sizeof(struct s1), DATA_LEN)))
979  return NC_ENOMEM;
980      memcpy((void *)data_out, (void *)dummy, sizeof(struct s1) * DATA_LEN);
981      free(dummy);
982
983      /* Create some phony data. */
984      for (idx = 0; idx < DATA_LENidx++)
985      {
986  data_out[idx].i = 20000;
987  data_out[idx].j = 300000;
988      }
989
990      /* Create a file with a compound type. Write a little data. */
991      if (nc_create(FILE_NAMENC_NETCDF4, &ncid)) ERR;
992      if (nc_def_compound(ncid, sizeof(struct s1), "cmp1", &typeid)) ERR;
993      if (nc_insert_compound(ncidtypeid, "i",
994      NC_COMPOUND_OFFSET(struct s1i), NC_SHORT)) ERR;
995      if (nc_insert_compound(ncidtypeid, "j",
996      NC_COMPOUND_OFFSET(struct s1j), NC_INT64)) ERR;
997      if (nc_def_dim(ncid, "phony_dim", 1, &dimid)) ERR;
998      if (nc_def_var(ncid, "phony_var", typeid, 1, dimids, &varid)) ERR;
999      if (nc_put_var(ncidvariddata_out)) ERR;
1000      if (nc_close(ncid)) ERR;
1001
1002      /* Reopen the file and check it. */
1003      if (nc_open(FILE_NAMENC_WRITE, &ncid)) ERR;
1004      if (nc_get_var(ncid, 0, data_in)) ERR;
1005      for (idx = 0; idx < DATA_LENidx++)
1006      {
1007  if (data_in[idx].i != data_out[idx].i ||
1008      data_in[idx].j != data_out[idx].jERR;
1009      }
1010      if (nc_close(ncid)) ERR;
1011   }
1012   SUMMARIZE_ERR;
1013   FINAL_RESULTS;
1014}


HyperKWIC - Version 7.20DA executed at 11:37 on 27 Oct 2017 | Polyhedron Solutions - INTERNAL USE | COMMERCIAL (Any O/S) SN 4AKIed