1 /* This is part of the netCDF package. Copyright 2005 University
2 Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
3 conditions of use. See www.unidata.ucar.edu for more info.
4
5 Test netcdf-4 cross platform compound type.
6
7 $Id: tst_xplatform2.c,v 1.18 2009/10/26 18:44:59 russ Exp $
8 */
9
10 #include <nc_tests.h>
11 #include "err_macros.h"
12 #include "netcdf.h"
13 #include <hdf5.h>
14
15 #define FILE_NAME_1 "tst_xplatform2_1.nc"
16 #define REF_FILE_NAME_1 "ref_tst_xplatform2_1.nc"
17 #define FILE_NAME_2 "tst_xplatform2_2.nc"
18 #define REF_FILE_NAME_2 "ref_tst_xplatform2_2.nc"
19 #define FILE_NAME_3 "tst_xplatform2_3.nc"
20 #define REF_FILE_NAME_3 "ref_tst_xplatform2_3.nc"
21 #define FILE_NAME_4 "tst_xplatform2_4.nc"
22 #define REF_FILE_NAME_4 "ref_tst_xplatform2_4.nc"
23
24 #define S1_TYPE_NAME "cmp_t"
25 #define X_NAME "x"
26 #define Y_NAME "y"
27 #define S1_NAME "s1"
28 #define S2_ATT_NAME "Runnymede"
29 #define S2_TYPE_NAME "date_1215"
30
31 #define DIM1_LEN 5
32 #define DIM2_LEN 3
33 #define VLEN_NAME "Magna_Carta_VLEN"
34 #define VLEN_ATT_NAME "We_will_sell_to_no_man_we_will_not_deny_or_defer_to_any_man_either_Justice_or_Right"
35 #define TWO_TYPES 2
36 #define NUM_S1 4
37
38 #define DIM3_LEN 1
39 #define DIM3_NAME "DIMENSION->The city of London shall enjoy all its ancient liberties and free customs, both by land and by water."
40 #define VAR3_NAME "VARIABLE->In future we will allow no one to levy an `aid' from his free men, except to ransom his person, to make his eldest son a knight, and (once) to marry his eldest daughter."
41
42 #define NUM_VL 1
43 #define S3_ATT_NAME "King_John"
44 #define S3_TYPE_NAME "barons"
45 #define VL_NAME "No scutage or aid may be levied in our kingdom without its general consent"
46 #define THREE_TYPES 3
47
48 struct s1
49 {
50 float x;
51 double y;
52 };
53 struct s2
54 {
55 struct s1 data[NUM_S1];
56 };
57 struct s3
58 {
59 nc_vlen_t data[NUM_VL];
60 };
61
62 int
check_file_1(int ncid,nc_vlen_t * data_out)63 check_file_1(int ncid, nc_vlen_t *data_out)
64 {
65 int ntypes_in, ndims_in;
66 char name_in[NC_MAX_NAME + 1];
67 size_t size_in, nfields_in, offset_in;
68 nc_type field_type_in;
69 nc_type typeids_in[TWO_TYPES], base_nc_type_in;
70 nc_vlen_t data_in[DIM1_LEN];
71 int i, j;
72
73 /* There should be two types. */
74 if (nc_inq_typeids(ncid, &ntypes_in, typeids_in)) ERR;
75 if (ntypes_in != 2) ERR;
76
77 /* The compound type is first: check it out. */
78 if (nc_inq_compound(ncid, typeids_in[0], name_in, &size_in, &nfields_in)) ERR;
79 if (nfields_in != 2 || strcmp(name_in, S1_TYPE_NAME) || size_in != sizeof(struct s1)) ERR;
80 if (nc_inq_compound_field(ncid, typeids_in[0], 0, name_in, &offset_in,
81 &field_type_in, &ndims_in, NULL)) ERR;
82 if (strcmp(name_in, X_NAME) || offset_in != 0 || field_type_in != NC_FLOAT ||
83 ndims_in) ERR;
84 if (nc_inq_compound_field(ncid, typeids_in[0], 1, name_in, &offset_in,
85 &field_type_in, &ndims_in, NULL)) ERR;
86 if (strcmp(name_in, Y_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s1, y) || field_type_in != NC_DOUBLE ||
87 ndims_in) ERR;
88
89 /* How does the vlen type look? */
90 if (nc_inq_vlen(ncid, typeids_in[1], name_in, &size_in, &base_nc_type_in)) ERR;
91 if (strcmp(name_in, VLEN_NAME) || size_in != sizeof(nc_vlen_t) ||
92 base_nc_type_in != typeids_in[0]) ERR;
93
94 /* Now read the attribute. */
95 if (nc_get_att(ncid, NC_GLOBAL, VLEN_ATT_NAME, data_in)) ERR;
96
97 /* Did we get the correct data? */
98 for (i = 0; i < DIM1_LEN; i++)
99 {
100 if (data_in[i].len != data_out[i].len) ERR;
101 for (j = 0; j < data_in[i].len; j++)
102 if (((struct s1 *)data_in[i].p)->x != ((struct s1 *)data_out[i].p)->x ||
103 ((struct s1 *)data_in[i].p)->y != ((struct s1 *)data_out[i].p)->y) ERR_RET;
104 }
105
106 /* Free the memory that was malloced when the VLEN was read. */
107 for (i = 0; i < DIM1_LEN; i++)
108 free(data_in[i].p);
109
110 /* We're done! */
111 return NC_NOERR;
112 }
113
114 int
check_file_2(int ncid,struct s2 * data_out)115 check_file_2(int ncid, struct s2 *data_out)
116 {
117 int ntypes_in, ndims_in;
118 char name_in[NC_MAX_NAME + 1];
119 size_t size_in, nfields_in, offset_in;
120 nc_type field_type_in;
121 nc_type typeids_in[TWO_TYPES];
122 struct s2 data_in[DIM2_LEN];
123 int field_dims_in[1];
124 int i, j;
125
126 /* There should be two types. */
127 if (nc_inq_typeids(ncid, &ntypes_in, typeids_in)) ERR;
128 if (ntypes_in != TWO_TYPES) ERR;
129
130 /* The compound type is first: check it out. */
131 if (nc_inq_compound(ncid, typeids_in[0], name_in, &size_in, &nfields_in)) ERR;
132 if (nfields_in != 2 || strcmp(name_in, S1_TYPE_NAME) || size_in != sizeof(struct s1)) ERR;
133 if (nc_inq_compound_field(ncid, typeids_in[0], 0, name_in, &offset_in,
134 &field_type_in, &ndims_in, NULL)) ERR;
135 if (strcmp(name_in, X_NAME) || offset_in != 0 || field_type_in != NC_FLOAT ||
136 ndims_in) ERR;
137 if (nc_inq_compound_field(ncid, typeids_in[0], 1, name_in, &offset_in,
138 &field_type_in, &ndims_in, NULL)) ERR;
139 if (strcmp(name_in, Y_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s1, y) || field_type_in != NC_DOUBLE ||
140 ndims_in) ERR;
141
142 /* How does the containing compound type look? */
143 if (nc_inq_compound(ncid, typeids_in[1], name_in, &size_in, &nfields_in)) ERR;
144 if (strcmp(name_in, S2_TYPE_NAME) || size_in != sizeof(struct s2) ||
145 nfields_in != 1) ERR;
146 if (nc_inq_compound_field(ncid, typeids_in[1], 0, name_in, &offset_in, &field_type_in,
147 &ndims_in, field_dims_in)) ERR;
148 if (strcmp(name_in, S1_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s2, data) ||
149 field_type_in != typeids_in[0] || ndims_in != 1 || field_dims_in[0] != NUM_S1) ERR;
150
151 /* Now read the attribute. */
152 if (nc_get_att(ncid, NC_GLOBAL, S2_ATT_NAME, data_in)) ERR;
153
154 /* Did we get the correct data? */
155 for (i = 0; i < DIM2_LEN; i++)
156 for (j = 0; j < NUM_S1; j++)
157 if (data_out[i].data[j].x != data_in[i].data[j].x ||
158 data_out[i].data[j].y != data_in[i].data[j].y) ERR;
159
160 /* We're done! */
161 return NC_NOERR;
162 }
163
164 int
check_file_3(int ncid,struct s3 * data_out)165 check_file_3(int ncid, struct s3 *data_out)
166 {
167 int ntypes_in, ndims_in;
168 char name_in[NC_MAX_NAME + 1];
169 size_t size_in, nfields_in, offset_in;
170 nc_type field_type_in, base_nc_type_in;
171 nc_type typeids_in[THREE_TYPES];
172 struct s3 data_in[DIM3_LEN];
173 int field_dims_in[1];
174 int i, j, k;
175
176 /* There should be three types. */
177 if (nc_inq_typeids(ncid, &ntypes_in, typeids_in)) ERR;
178 if (ntypes_in != THREE_TYPES) ERR;
179
180 /* The s1 compound type is first: check it out. */
181 if (nc_inq_compound(ncid, typeids_in[0], name_in, &size_in, &nfields_in)) ERR;
182 if (nfields_in != 2 || strcmp(name_in, S1_TYPE_NAME) || size_in != sizeof(struct s1)) ERR;
183 if (nc_inq_compound_field(ncid, typeids_in[0], 0, name_in, &offset_in,
184 &field_type_in, &ndims_in, NULL)) ERR;
185 if (strcmp(name_in, X_NAME) || offset_in != 0 || field_type_in != NC_FLOAT ||
186 ndims_in) ERR;
187 if (nc_inq_compound_field(ncid, typeids_in[0], 1, name_in, &offset_in,
188 &field_type_in, &ndims_in, NULL)) ERR;
189 if (strcmp(name_in, Y_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s1, y) || field_type_in != NC_DOUBLE ||
190 ndims_in) ERR;
191
192 /* How does the vlen type look? */
193 if (nc_inq_vlen(ncid, typeids_in[1], name_in, &size_in, &base_nc_type_in)) ERR;
194 if (strcmp(name_in, VLEN_NAME) || size_in != sizeof(nc_vlen_t) ||
195 base_nc_type_in != typeids_in[0]) ERR;
196
197 /* How does the containing compound type look? */
198 if (nc_inq_compound(ncid, typeids_in[2], name_in, &size_in, &nfields_in)) ERR;
199 if (strcmp(name_in, S3_TYPE_NAME) || size_in != sizeof(struct s3) ||
200 nfields_in != 1) ERR;
201 if (nc_inq_compound_field(ncid, typeids_in[2], 0, name_in, &offset_in, &field_type_in,
202 &ndims_in, field_dims_in)) ERR;
203 if (strcmp(name_in, VL_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s3, data) ||
204 field_type_in != typeids_in[1] || ndims_in != 1 || field_dims_in[0] != NUM_VL) ERR;
205
206 /* Now read the attribute. */
207 if (nc_get_att(ncid, NC_GLOBAL, S3_ATT_NAME, data_in)) ERR;
208
209 /* Did we get the correct data? */
210 for (i = 0; i < DIM3_LEN; i++)
211 for (j = 0; j < NUM_VL; j++)
212 {
213 if (data_in[i].data[j].len != data_out[i].data[j].len) ERR;
214 for (k = 0; k < data_out[i].data[j].len; k++)
215 if (((struct s1 *)data_in[i].data[j].p)[k].x != ((struct s1 *)data_out[i].data[j].p)[k].x ||
216 ((struct s1 *)data_in[i].data[j].p)[k].y != ((struct s1 *)data_out[i].data[j].p)[k].y) ERR;
217 }
218
219 /* Free our vlens. */
220 for (i = 0; i < DIM3_LEN; i++)
221 for (j = 0; j < NUM_VL; j++)
222 nc_free_vlen(&(data_in[i].data[j]));
223
224 /* We're done! */
225 return NC_NOERR;
226 }
227
228 int
check_file_4(int ncid,struct s3 * data_out)229 check_file_4(int ncid, struct s3 *data_out)
230 {
231 int ntypes_in, ndims_in;
232 char name_in[NC_MAX_NAME + 1];
233 size_t size_in, nfields_in, offset_in;
234 nc_type field_type_in, base_nc_type_in;
235 nc_type typeids_in[THREE_TYPES];
236 struct s3 data_in[DIM3_LEN];
237 int field_dims_in[1];
238 int i, j, k;
239
240 /* There should be three types. */
241 if (nc_inq_typeids(ncid, &ntypes_in, typeids_in)) ERR;
242 if (ntypes_in != THREE_TYPES) ERR;
243
244 /* The s1 compound type is first: check it out. */
245 if (nc_inq_compound(ncid, typeids_in[0], name_in, &size_in, &nfields_in)) ERR;
246 if (nfields_in != 2 || strcmp(name_in, S1_TYPE_NAME) || size_in != sizeof(struct s1)) ERR;
247 if (nc_inq_compound_field(ncid, typeids_in[0], 0, name_in, &offset_in,
248 &field_type_in, &ndims_in, NULL)) ERR;
249 if (strcmp(name_in, X_NAME) || offset_in != 0 || field_type_in != NC_FLOAT ||
250 ndims_in) ERR;
251 if (nc_inq_compound_field(ncid, typeids_in[0], 1, name_in, &offset_in,
252 &field_type_in, &ndims_in, NULL)) ERR;
253 if (strcmp(name_in, Y_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s1, y) || field_type_in != NC_DOUBLE ||
254 ndims_in) ERR;
255
256 /* How does the vlen type look? */
257 if (nc_inq_vlen(ncid, typeids_in[1], name_in, &size_in, &base_nc_type_in)) ERR;
258 if (strcmp(name_in, VLEN_NAME) || size_in != sizeof(nc_vlen_t) ||
259 base_nc_type_in != typeids_in[0]) ERR;
260
261 /* How does the containing compound type look? */
262 if (nc_inq_compound(ncid, typeids_in[2], name_in, &size_in, &nfields_in)) ERR;
263 if (strcmp(name_in, S3_TYPE_NAME) || size_in != sizeof(struct s3) ||
264 nfields_in != 1) ERR;
265 if (nc_inq_compound_field(ncid, typeids_in[2], 0, name_in, &offset_in, &field_type_in,
266 &ndims_in, field_dims_in)) ERR;
267 if (strcmp(name_in, VL_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s3, data) ||
268 field_type_in != typeids_in[1] || ndims_in != 1 || field_dims_in[0] != NUM_VL) ERR;
269
270 /* Now read the variable. */
271 if (nc_get_var(ncid, 0, data_in)) ERR;
272
273 /* Did we get the correct data? */
274 for (i = 0; i < DIM3_LEN; i++)
275 for (j = 0; j < NUM_VL; j++)
276 {
277 if (data_in[i].data[j].len != data_out[i].data[j].len) ERR;
278 for (k = 0; k < data_out[i].data[j].len; k++)
279 if (((struct s1 *)data_in[i].data[j].p)[k].x != ((struct s1 *)data_out[i].data[j].p)[k].x ||
280 ((struct s1 *)data_in[i].data[j].p)[k].y != ((struct s1 *)data_out[i].data[j].p)[k].y) ERR;
281 }
282
283 /* Free our vlens. */
284 for (i = 0; i < DIM3_LEN; i++)
285 for (j = 0; j < NUM_VL; j++)
286 nc_free_vlen(&(data_in[i].data[j]));
287
288 /* We're done! */
289 return NC_NOERR;
290 }
291
292 int
main(int argc,char ** argv)293 main(int argc, char **argv)
294 {
295 int ncid;
296 int i, j, k;
297 nc_vlen_t *vlen_of_comp_out;
298 struct s2 *comp_array_of_comp_out;
299 struct s3 *comp_array_of_vlen_of_comp_out;
300
301 printf("\nTesting nested types across platforms.\n");
302
303 if (!(vlen_of_comp_out = calloc(sizeof(nc_vlen_t), DIM1_LEN))) ERR;
304 if (!(comp_array_of_comp_out = calloc(sizeof(struct s2), DIM2_LEN))) ERR;
305 if (!(comp_array_of_vlen_of_comp_out = calloc(sizeof(struct s3), DIM3_LEN))) ERR;
306
307 /* Create some output data: a vlen of struct s1. */
308 for (i = 0; i < DIM1_LEN; i++)
309 {
310 vlen_of_comp_out[i].len = i + 1;
311 if (!(vlen_of_comp_out[i].p = malloc(sizeof(struct s1) * vlen_of_comp_out[i].len)))
312 return NC_ENOMEM;
313 for (j = 0; j < vlen_of_comp_out[i].len; j++)
314 {
315 ((struct s1 *)vlen_of_comp_out[i].p)[j].x = 42.42;
316 ((struct s1 *)vlen_of_comp_out[i].p)[j].y = 2.0;
317 }
318 }
319
320 /* Create some output data: a struct which holds an array of
321 * struct s1. */
322 for (i = 0; i < DIM2_LEN; i++)
323 for (j = 0; j < NUM_S1; j++)
324 {
325 comp_array_of_comp_out[i].data[j].x = 42.42;
326 comp_array_of_comp_out[i].data[j].y = 2.0;
327 }
328
329 /* Create some output data: a struct which holds an array of
330 * vlen of struct s1. */
331 for (i = 0; i < DIM3_LEN; i++)
332 for (j = 0; j < NUM_VL; j++)
333 {
334 comp_array_of_vlen_of_comp_out[i].data[j].len = i + 1;
335 if (!(comp_array_of_vlen_of_comp_out[i].data[j].p = malloc(sizeof(struct s1) * comp_array_of_vlen_of_comp_out[i].data[j].len)))
336 return NC_ENOMEM;
337 for (k = 0; k < comp_array_of_vlen_of_comp_out[i].data[j].len; k++)
338 {
339 ((struct s1 *)comp_array_of_vlen_of_comp_out[i].data[j].p)[k].x = 42.42;
340 ((struct s1 *)comp_array_of_vlen_of_comp_out[i].data[j].p)[k].y = 2.0;
341 }
342 }
343
344 printf("*** testing of vlen of compound type...");
345 {
346 nc_type s1_typeid, vlen_typeid;
347
348 /* Create a netCDF-4 file. */
349 if (nc_create(FILE_NAME_1, NC_NETCDF4, &ncid)) ERR;
350
351 /* Create a simple compound type which has different sizes on
352 * different platforms - our old friend struct s1. */
353 if (nc_def_compound(ncid, sizeof(struct s1), S1_TYPE_NAME, &s1_typeid)) ERR;
354 if (nc_insert_compound(ncid, s1_typeid, X_NAME,
355 NC_COMPOUND_OFFSET(struct s1, x), NC_FLOAT)) ERR;
356 if (nc_insert_compound(ncid, s1_typeid, Y_NAME,
357 NC_COMPOUND_OFFSET(struct s1, y), NC_DOUBLE)) ERR;
358
359 /* Now make a new type: a vlen of our compound type. */
360 if (nc_def_vlen(ncid, VLEN_NAME, s1_typeid, &vlen_typeid)) ERR;
361
362 /* Write the output data as an attribute. */
363 if (nc_put_att(ncid, NC_GLOBAL, VLEN_ATT_NAME, vlen_typeid,
364 DIM1_LEN, vlen_of_comp_out)) ERR;
365
366 /* How does it look? */
367 if (check_file_1(ncid, vlen_of_comp_out)) ERR;
368
369 /* We're done - wasn't that easy? */
370 if (nc_close(ncid)) ERR;
371
372 /* Check it out. */
373 if (nc_open(FILE_NAME_1, NC_NOWRITE, &ncid)) ERR;
374 if (check_file_1(ncid, vlen_of_comp_out)) ERR;
375 if (nc_close(ncid)) ERR;
376 }
377 SUMMARIZE_ERR;
378 printf("*** testing Solaris-written vlen of compound type...");
379 {
380 char file_in[NC_MAX_NAME + 1];
381
382 strcpy(file_in, "");
383 if (getenv("srcdir"))
384 {
385 strcat(file_in, getenv("srcdir"));
386 strcat(file_in, "/");
387 }
388 strcat(file_in, REF_FILE_NAME_1);
389
390 /* Check out the same file, generated on buddy and included with
391 * the distribution. */
392 if (nc_open(file_in, NC_NOWRITE, &ncid)) ERR;
393 if (check_file_1(ncid, vlen_of_comp_out)) ERR;
394 if (nc_close(ncid)) ERR;
395 }
396 SUMMARIZE_ERR;
397 printf("*** testing compound type containing array of compound type...");
398 {
399 nc_type s1_typeid, s2_typeid;
400 int dimsizes[1] = {NUM_S1};
401
402 /* Create a netCDF-4 file. */
403 if (nc_create(FILE_NAME_2, NC_NETCDF4, &ncid)) ERR;
404
405 /* Create a simple compound type which has different sizes on
406 * different platforms - our old friend struct s1. */
407 if (nc_def_compound(ncid, sizeof(struct s1), S1_TYPE_NAME, &s1_typeid)) ERR;
408 if (nc_insert_compound(ncid, s1_typeid, X_NAME,
409 NC_COMPOUND_OFFSET(struct s1, x), NC_FLOAT)) ERR;
410 if (nc_insert_compound(ncid, s1_typeid, Y_NAME,
411 NC_COMPOUND_OFFSET(struct s1, y), NC_DOUBLE)) ERR;
412
413 /* Now make a compound type that holds an array of the struct s1
414 * type. */
415 if (nc_def_compound(ncid, sizeof(struct s2), S2_TYPE_NAME, &s2_typeid)) ERR;
416 if (nc_insert_array_compound(ncid, s2_typeid, S1_NAME,
417 NC_COMPOUND_OFFSET(struct s2, data),
418 s1_typeid, 1, dimsizes)) ERR;
419
420
421 /* Write the output data as an attribute. */
422 if (nc_put_att(ncid, NC_GLOBAL, S2_ATT_NAME, s2_typeid,
423 DIM2_LEN, comp_array_of_comp_out)) ERR;
424
425 /* How does it look? */
426 if (check_file_2(ncid, comp_array_of_comp_out)) ERR;
427
428 /* We're done - wasn't that easy? */
429 if (nc_close(ncid)) ERR;
430
431 /* Check it out. */
432 if (nc_open(FILE_NAME_2, NC_NOWRITE, &ncid)) ERR;
433 if (check_file_2(ncid, comp_array_of_comp_out)) ERR;
434 if (nc_close(ncid)) ERR;
435 }
436 SUMMARIZE_ERR;
437 printf("*** testing Solaris-written compound type containing array of compound type...");
438 {
439 char file_in[NC_MAX_NAME + 1];
440
441 strcpy(file_in, "");
442 if (getenv("srcdir"))
443 {
444 strcat(file_in, getenv("srcdir"));
445 strcat(file_in, "/");
446 }
447 strcat(file_in, REF_FILE_NAME_2);
448
449 /* Check out the same file, generated on buddy and included with
450 * the distribution. */
451 if (nc_open(file_in, NC_NOWRITE, &ncid)) ERR;
452 if (check_file_2(ncid, comp_array_of_comp_out)) ERR;
453 if (nc_close(ncid)) ERR;
454 }
455 SUMMARIZE_ERR;
456 printf("*** testing compound attribute containing array of vlen of compound type...");
457 {
458 nc_type vlen_typeid, s3_typeid, s1_typeid;
459 int dimsizes[1] = {NUM_VL};
460
461 /* Create a netCDF-4 file. */
462 if (nc_create(FILE_NAME_3, NC_NETCDF4, &ncid)) ERR;
463
464 /* Create a simple compound type which has different sizes on
465 * different platforms - our old friend struct s1. */
466 if (nc_def_compound(ncid, sizeof(struct s1), S1_TYPE_NAME, &s1_typeid)) ERR;
467 if (nc_insert_compound(ncid, s1_typeid, X_NAME,
468 NC_COMPOUND_OFFSET(struct s1, x), NC_FLOAT)) ERR;
469 if (nc_insert_compound(ncid, s1_typeid, Y_NAME,
470 NC_COMPOUND_OFFSET(struct s1, y), NC_DOUBLE)) ERR;
471
472 /* Now make a new type: a vlen of our s1 compound type. */
473 if (nc_def_vlen(ncid, VLEN_NAME, s1_typeid, &vlen_typeid)) ERR;
474
475 /* Now make a compound type that holds an array of the VLEN
476 * type. */
477 if (nc_def_compound(ncid, sizeof(struct s3), S3_TYPE_NAME, &s3_typeid)) ERR;
478 if (nc_insert_array_compound(ncid, s3_typeid, VL_NAME,
479 NC_COMPOUND_OFFSET(struct s3, data),
480 vlen_typeid, 1, dimsizes)) ERR;
481
482
483 /* Write the output data as an attribute. */
484 if (nc_put_att(ncid, NC_GLOBAL, S3_ATT_NAME, s3_typeid,
485 DIM3_LEN, comp_array_of_vlen_of_comp_out)) ERR;
486
487 /* How does it look? Uncomment this line to see memory issue. */
488 /* if (check_file_3(ncid, comp_array_of_vlen_of_comp_out)) ERR; */
489
490 /* We're done - wasn't that easy? */
491 if (nc_close(ncid)) ERR;
492
493 /* Check it out. */
494 if (nc_open(FILE_NAME_3, NC_NOWRITE, &ncid)) ERR;
495 if (check_file_3(ncid, comp_array_of_vlen_of_comp_out)) ERR;
496 if (nc_close(ncid)) ERR;
497 }
498 SUMMARIZE_ERR;
499 printf("*** testing compound variable containing array of vlen of compound type...");
500 {
501 nc_type vlen_typeid, s3_typeid, s1_typeid;
502 int varid, dimid;
503 int dimsizes[1] = {NUM_VL};
504
505 /* Create a netCDF-4 file. */
506 if (nc_create(FILE_NAME_4, NC_NETCDF4, &ncid)) ERR;
507
508 /* Create a simple compound type which has different sizes on
509 * different platforms - our old friend struct s1. */
510 if (nc_def_compound(ncid, sizeof(struct s1), S1_TYPE_NAME, &s1_typeid)) ERR;
511 if (nc_insert_compound(ncid, s1_typeid, X_NAME,
512 NC_COMPOUND_OFFSET(struct s1, x), NC_FLOAT)) ERR;
513 if (nc_insert_compound(ncid, s1_typeid, Y_NAME,
514 NC_COMPOUND_OFFSET(struct s1, y), NC_DOUBLE)) ERR;
515
516 /* Now make a new type: a vlen of our s1 compound type. */
517 if (nc_def_vlen(ncid, VLEN_NAME, s1_typeid, &vlen_typeid)) ERR;
518
519 /* Now make a compound type that holds an array of the VLEN
520 * type. */
521 if (nc_def_compound(ncid, sizeof(struct s3), S3_TYPE_NAME, &s3_typeid)) ERR;
522 if (nc_insert_array_compound(ncid, s3_typeid, VL_NAME,
523 NC_COMPOUND_OFFSET(struct s3, data),
524 vlen_typeid, 1, dimsizes)) ERR;
525
526 /* Create a dimension and a var of s3 type, then write the
527 * data. */
528 if (nc_def_dim(ncid, DIM3_NAME, DIM3_LEN, &dimid)) ERR;
529 if (nc_def_var(ncid, VAR3_NAME, s3_typeid, 1, &dimid, &varid)) ERR;
530 if (nc_put_var(ncid, varid, comp_array_of_vlen_of_comp_out)) ERR;
531
532 /* How does it look? */
533 if (check_file_4(ncid, comp_array_of_vlen_of_comp_out)) ERR;
534
535 /* We're done - wasn't that easy? */
536 if (nc_close(ncid)) ERR;
537
538 /* Check it out. */
539 if (nc_open(FILE_NAME_4, NC_NOWRITE, &ncid)) ERR;
540 if (check_file_4(ncid, comp_array_of_vlen_of_comp_out)) ERR;
541 if (nc_close(ncid)) ERR;
542 }
543 SUMMARIZE_ERR;
544
545 /* Free our mallocs. */
546 for (i = 0; i < DIM1_LEN; i++)
547 free(vlen_of_comp_out[i].p);
548 for (i = 0; i < DIM3_LEN; i++)
549 for (j = 0; j < NUM_VL; j++)
550 free(comp_array_of_vlen_of_comp_out[i].data[j].p);
551
552 free(comp_array_of_comp_out);
553 free(comp_array_of_vlen_of_comp_out);
554 free(vlen_of_comp_out);
555
556 /* Now run the tests formerly in tst_h_atts2.c. */
557 #define REF_FILE_NAME "tst_xplatform2_3.nc"
558 #define NUM_OBJ 3
559
560 printf("\n*** Checking HDF5 attribute functions some more.\n");
561 printf("*** Opening tst_xplatform2_3.nc...");
562 {
563 hid_t fileid, grpid, attid;
564 hid_t file_typeid1[NUM_OBJ], native_typeid1[NUM_OBJ];
565 hid_t file_typeid2, native_typeid2;
566 hsize_t num_obj, i;
567 H5O_info_t obj_info;
568 char obj_name[NC_MAX_NAME + 1];
569
570 /* Open one of the netCDF test files. */
571 if ((fileid = H5Fopen(REF_FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
572 if ((grpid = H5Gopen(fileid, "/")) < 0) ERR;
573
574 /* How many objects in this group? */
575 if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
576 if (num_obj != NUM_OBJ) ERR;
577
578 /* For each object in the group... */
579 for (i = 0; i < num_obj; i++)
580 {
581 /* Get the name. */
582 if (H5Oget_info_by_idx(grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC,
583 i, &obj_info, H5P_DEFAULT) < 0) ERR_RET;
584 if (H5Lget_name_by_idx(grpid, ".", H5_INDEX_NAME, H5_ITER_INC, i,
585 obj_name, NC_MAX_NAME + 1, H5P_DEFAULT) < 0) ERR_RET;
586 printf(" reading type %s ", obj_name);
587 if (obj_info.type != H5O_TYPE_NAMED_DATATYPE) ERR_RET;
588
589 /* Get the typeid. */
590 if ((file_typeid1[i] = H5Topen2(grpid, obj_name, H5P_DEFAULT)) < 0) ERR_RET;
591 if ((native_typeid1[i] = H5Tget_native_type(file_typeid1[i], H5T_DIR_DEFAULT)) < 0) ERR_RET;
592 }
593
594 /* There is one att: open it by index. */
595 if ((attid = H5Aopen_idx(grpid, 0)) < 0) ERR;
596
597 /* Get file and native typeids. */
598 if ((file_typeid2 = H5Aget_type(attid)) < 0) ERR;
599 if ((native_typeid2 = H5Tget_native_type(file_typeid2, H5T_DIR_DEFAULT)) < 0) ERR;
600
601 /* Close the attribute. */
602 if (H5Aclose(attid) < 0) ERR;
603
604 /* Close the typeids. */
605 if (H5Tclose(file_typeid2) < 0) ERR_RET;
606 if (H5Tclose(native_typeid2) < 0) ERR_RET;
607 for (i = 0; i < NUM_OBJ; i++)
608 {
609 if (H5Tclose(file_typeid1[i]) < 0) ERR_RET;
610 if (H5Tclose(native_typeid1[i]) < 0) ERR_RET;
611 }
612
613 /* Close the group and file. */
614 if (H5Gclose(grpid) < 0 ||
615 H5Fclose(fileid) < 0) ERR;
616 }
617
618 SUMMARIZE_ERR;
619 printf("*** Opening tst_xplatform2_3.nc again...");
620 {
621 hid_t fileid, grpid, attid, file_typeid, native_typeid;
622 hid_t file_typeid2, native_typeid2;
623
624 /* Open one of the netCDF test files. */
625 if ((fileid = H5Fopen(REF_FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
626 if ((grpid = H5Gopen(fileid, "/")) < 0) ERR;
627
628 /* There is one att: open it by index. */
629 if ((attid = H5Aopen_idx(grpid, 0)) < 0) ERR;
630
631 /* Get file and native typeids. */
632 if ((file_typeid = H5Aget_type(attid)) < 0) ERR;
633 if ((native_typeid = H5Tget_native_type(file_typeid, H5T_DIR_DEFAULT)) < 0) ERR;
634
635 /* Now getting another copy of the native typeid will fail! WTF? */
636 if ((file_typeid2 = H5Aget_type(attid)) < 0) ERR;
637 if ((native_typeid2 = H5Tget_native_type(file_typeid, H5T_DIR_DEFAULT)) < 0) ERR;
638
639 /* Close the attribute. */
640 if (H5Aclose(attid) < 0) ERR;
641
642 /* Close the typeids. */
643 if (H5Tclose(file_typeid) < 0) ERR;
644 if (H5Tclose(native_typeid) < 0) ERR;
645 if (H5Tclose(file_typeid2) < 0) ERR;
646 if (H5Tclose(native_typeid2) < 0) ERR;
647
648 /* Close the group and file. */
649 if (H5Gclose(grpid) < 0 ||
650 H5Fclose(fileid) < 0) ERR;
651 }
652 SUMMARIZE_ERR;
653 FINAL_RESULTS;
654 }
655