mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-12-15 08:30:11 +08:00
664 lines
24 KiB
C
664 lines
24 KiB
C
/* This is part of the netCDF package. Copyright 2018 University
|
|
Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
|
|
conditions of use. See www.unidata.ucar.edu for more info.
|
|
|
|
Test netcdf-4 cross platform compound type.
|
|
|
|
$Id: tst_xplatform2.c,v 1.18 2009/10/26 18:44:59 russ Exp $
|
|
*/
|
|
|
|
#include <nc_tests.h>
|
|
#include "err_macros.h"
|
|
#include "netcdf.h"
|
|
#include <hdf5.h>
|
|
|
|
#define FILE_NAME_1 "tst_xplatform2_1.nc"
|
|
#define REF_FILE_NAME_1 "ref_tst_xplatform2_1.nc"
|
|
#define FILE_NAME_2 "tst_xplatform2_2.nc"
|
|
#define REF_FILE_NAME_2 "ref_tst_xplatform2_2.nc"
|
|
#define FILE_NAME_3 "tst_xplatform2_3.nc"
|
|
#define REF_FILE_NAME_3 "ref_tst_xplatform2_3.nc"
|
|
#define FILE_NAME_4 "tst_xplatform2_4.nc"
|
|
#define REF_FILE_NAME_4 "ref_tst_xplatform2_4.nc"
|
|
|
|
#define S1_TYPE_NAME "cmp_t"
|
|
#define X_NAME "x"
|
|
#define Y_NAME "y"
|
|
#define S1_NAME "s1"
|
|
#define S2_ATT_NAME "Runnymede"
|
|
#define S2_TYPE_NAME "date_1215"
|
|
|
|
#define DIM1_LEN 5
|
|
#define DIM2_LEN 3
|
|
#define VLEN_NAME "Magna_Carta_VLEN"
|
|
#define VLEN_ATT_NAME "We_will_sell_to_no_man_we_will_not_deny_or_defer_to_any_man_either_Justice_or_Right"
|
|
#define TWO_TYPES 2
|
|
#define NUM_S1 4
|
|
|
|
#define DIM3_LEN 1
|
|
#define DIM3_NAME "DIMENSION->The city of London shall enjoy all its ancient liberties and free customs, both by land and by water."
|
|
#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."
|
|
|
|
#define NUM_VL 1
|
|
#define S3_ATT_NAME "King_John"
|
|
#define S3_TYPE_NAME "barons"
|
|
#define VL_NAME "No scutage or aid may be levied in our kingdom without its general consent"
|
|
#define THREE_TYPES 3
|
|
|
|
struct s1
|
|
{
|
|
float x;
|
|
double y;
|
|
};
|
|
struct s2
|
|
{
|
|
struct s1 data[NUM_S1];
|
|
};
|
|
struct s3
|
|
{
|
|
nc_vlen_t data[NUM_VL];
|
|
};
|
|
|
|
int
|
|
check_file_1(int ncid, nc_vlen_t *data_out)
|
|
{
|
|
int ntypes_in, ndims_in;
|
|
char name_in[NC_MAX_NAME + 1];
|
|
size_t size_in, nfields_in, offset_in;
|
|
nc_type field_type_in;
|
|
nc_type typeids_in[TWO_TYPES], base_nc_type_in;
|
|
nc_vlen_t data_in[DIM1_LEN];
|
|
int i, j;
|
|
|
|
/* There should be two types. */
|
|
if (nc_inq_typeids(ncid, &ntypes_in, typeids_in)) ERR;
|
|
if (ntypes_in != 2) ERR;
|
|
|
|
/* The compound type is first: check it out. */
|
|
if (nc_inq_compound(ncid, typeids_in[0], name_in, &size_in, &nfields_in)) ERR;
|
|
if (nfields_in != 2 || strcmp(name_in, S1_TYPE_NAME) || size_in != sizeof(struct s1)) ERR;
|
|
if (nc_inq_compound_field(ncid, typeids_in[0], 0, name_in, &offset_in,
|
|
&field_type_in, &ndims_in, NULL)) ERR;
|
|
if (strcmp(name_in, X_NAME) || offset_in != 0 || field_type_in != NC_FLOAT ||
|
|
ndims_in) ERR;
|
|
if (nc_inq_compound_field(ncid, typeids_in[0], 1, name_in, &offset_in,
|
|
&field_type_in, &ndims_in, NULL)) ERR;
|
|
if (strcmp(name_in, Y_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s1, y) || field_type_in != NC_DOUBLE ||
|
|
ndims_in) ERR;
|
|
|
|
/* How does the vlen type look? */
|
|
if (nc_inq_vlen(ncid, typeids_in[1], name_in, &size_in, &base_nc_type_in)) ERR;
|
|
if (strcmp(name_in, VLEN_NAME) || size_in != sizeof(nc_vlen_t) ||
|
|
base_nc_type_in != typeids_in[0]) ERR;
|
|
|
|
/* Now read the attribute. */
|
|
if (nc_get_att(ncid, NC_GLOBAL, VLEN_ATT_NAME, data_in)) ERR;
|
|
|
|
/* Did we get the correct data? */
|
|
for (i = 0; i < DIM1_LEN; i++)
|
|
{
|
|
if (data_in[i].len != data_out[i].len) ERR;
|
|
for (j = 0; j < data_in[i].len; j++)
|
|
if (((struct s1 *)data_in[i].p)->x != ((struct s1 *)data_out[i].p)->x ||
|
|
((struct s1 *)data_in[i].p)->y != ((struct s1 *)data_out[i].p)->y) ERR_RET;
|
|
}
|
|
|
|
/* Free the memory that was malloced when the VLEN was read. */
|
|
for (i = 0; i < DIM1_LEN; i++)
|
|
free(data_in[i].p);
|
|
|
|
/* We're done! */
|
|
return NC_NOERR;
|
|
}
|
|
|
|
int
|
|
check_file_2(int ncid, struct s2 *data_out)
|
|
{
|
|
int ntypes_in, ndims_in;
|
|
char name_in[NC_MAX_NAME + 1];
|
|
size_t size_in, nfields_in, offset_in;
|
|
nc_type field_type_in;
|
|
nc_type typeids_in[TWO_TYPES];
|
|
struct s2 data_in[DIM2_LEN];
|
|
int field_dims_in[1];
|
|
int i, j;
|
|
|
|
/* There should be two types. */
|
|
if (nc_inq_typeids(ncid, &ntypes_in, typeids_in)) ERR;
|
|
if (ntypes_in != TWO_TYPES) ERR;
|
|
|
|
/* The compound type is first: check it out. */
|
|
if (nc_inq_compound(ncid, typeids_in[0], name_in, &size_in, &nfields_in)) ERR;
|
|
if (nfields_in != 2 || strcmp(name_in, S1_TYPE_NAME) || size_in != sizeof(struct s1)) ERR;
|
|
if (nc_inq_compound_field(ncid, typeids_in[0], 0, name_in, &offset_in,
|
|
&field_type_in, &ndims_in, NULL)) ERR;
|
|
if (strcmp(name_in, X_NAME) || offset_in != 0 || field_type_in != NC_FLOAT ||
|
|
ndims_in) ERR;
|
|
if (nc_inq_compound_field(ncid, typeids_in[0], 1, name_in, &offset_in,
|
|
&field_type_in, &ndims_in, NULL)) ERR;
|
|
if (strcmp(name_in, Y_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s1, y) || field_type_in != NC_DOUBLE ||
|
|
ndims_in) ERR;
|
|
|
|
/* How does the containing compound type look? */
|
|
if (nc_inq_compound(ncid, typeids_in[1], name_in, &size_in, &nfields_in)) ERR;
|
|
if (strcmp(name_in, S2_TYPE_NAME) || size_in != sizeof(struct s2) ||
|
|
nfields_in != 1) ERR;
|
|
if (nc_inq_compound_field(ncid, typeids_in[1], 0, name_in, &offset_in, &field_type_in,
|
|
&ndims_in, field_dims_in)) ERR;
|
|
if (strcmp(name_in, S1_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s2, data) ||
|
|
field_type_in != typeids_in[0] || ndims_in != 1 || field_dims_in[0] != NUM_S1) ERR;
|
|
|
|
/* Now read the attribute. */
|
|
if (nc_get_att(ncid, NC_GLOBAL, S2_ATT_NAME, data_in)) ERR;
|
|
|
|
/* Did we get the correct data? */
|
|
for (i = 0; i < DIM2_LEN; i++)
|
|
for (j = 0; j < NUM_S1; j++)
|
|
if (data_out[i].data[j].x != data_in[i].data[j].x ||
|
|
data_out[i].data[j].y != data_in[i].data[j].y) ERR;
|
|
|
|
/* We're done! */
|
|
return NC_NOERR;
|
|
}
|
|
|
|
int
|
|
check_file_3(int ncid, struct s3 *data_out)
|
|
{
|
|
int ntypes_in, ndims_in;
|
|
char name_in[NC_MAX_NAME + 1];
|
|
size_t size_in, nfields_in, offset_in;
|
|
nc_type field_type_in, base_nc_type_in;
|
|
nc_type typeids_in[THREE_TYPES];
|
|
struct s3 data_in[DIM3_LEN];
|
|
int field_dims_in[1];
|
|
int i, j, k;
|
|
|
|
/* There should be three types. */
|
|
if (nc_inq_typeids(ncid, &ntypes_in, typeids_in)) ERR;
|
|
if (ntypes_in != THREE_TYPES) ERR;
|
|
|
|
/* The s1 compound type is first: check it out. */
|
|
if (nc_inq_compound(ncid, typeids_in[0], name_in, &size_in, &nfields_in)) ERR;
|
|
if (nfields_in != 2 || strcmp(name_in, S1_TYPE_NAME) || size_in != sizeof(struct s1)) ERR;
|
|
if (nc_inq_compound_field(ncid, typeids_in[0], 0, name_in, &offset_in,
|
|
&field_type_in, &ndims_in, NULL)) ERR;
|
|
if (strcmp(name_in, X_NAME) || offset_in != 0 || field_type_in != NC_FLOAT ||
|
|
ndims_in) ERR;
|
|
if (nc_inq_compound_field(ncid, typeids_in[0], 1, name_in, &offset_in,
|
|
&field_type_in, &ndims_in, NULL)) ERR;
|
|
if (strcmp(name_in, Y_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s1, y) || field_type_in != NC_DOUBLE ||
|
|
ndims_in) ERR;
|
|
|
|
/* How does the vlen type look? */
|
|
if (nc_inq_vlen(ncid, typeids_in[1], name_in, &size_in, &base_nc_type_in)) ERR;
|
|
if (strcmp(name_in, VLEN_NAME) || size_in != sizeof(nc_vlen_t) ||
|
|
base_nc_type_in != typeids_in[0]) ERR;
|
|
|
|
/* How does the containing compound type look? */
|
|
if (nc_inq_compound(ncid, typeids_in[2], name_in, &size_in, &nfields_in)) ERR;
|
|
if (strcmp(name_in, S3_TYPE_NAME) || size_in != sizeof(struct s3) ||
|
|
nfields_in != 1) ERR;
|
|
if (nc_inq_compound_field(ncid, typeids_in[2], 0, name_in, &offset_in, &field_type_in,
|
|
&ndims_in, field_dims_in)) ERR;
|
|
if (strcmp(name_in, VL_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s3, data) ||
|
|
field_type_in != typeids_in[1] || ndims_in != 1 || field_dims_in[0] != NUM_VL) ERR;
|
|
|
|
/* Now read the attribute. */
|
|
if (nc_get_att(ncid, NC_GLOBAL, S3_ATT_NAME, data_in)) ERR;
|
|
|
|
/* Did we get the correct data? */
|
|
for (i = 0; i < DIM3_LEN; i++)
|
|
for (j = 0; j < NUM_VL; j++)
|
|
{
|
|
if (data_in[i].data[j].len != data_out[i].data[j].len) ERR;
|
|
for (k = 0; k < data_out[i].data[j].len; k++)
|
|
if (((struct s1 *)data_in[i].data[j].p)[k].x != ((struct s1 *)data_out[i].data[j].p)[k].x ||
|
|
((struct s1 *)data_in[i].data[j].p)[k].y != ((struct s1 *)data_out[i].data[j].p)[k].y) ERR;
|
|
}
|
|
|
|
/* Free our vlens. */
|
|
for (i = 0; i < DIM3_LEN; i++)
|
|
for (j = 0; j < NUM_VL; j++)
|
|
nc_free_vlen(&(data_in[i].data[j]));
|
|
|
|
/* We're done! */
|
|
return NC_NOERR;
|
|
}
|
|
|
|
int
|
|
check_file_4(int ncid, struct s3 *data_out)
|
|
{
|
|
int ntypes_in, ndims_in;
|
|
char name_in[NC_MAX_NAME + 1];
|
|
size_t size_in, nfields_in, offset_in;
|
|
nc_type field_type_in, base_nc_type_in;
|
|
nc_type typeids_in[THREE_TYPES];
|
|
struct s3 data_in[DIM3_LEN];
|
|
int field_dims_in[1];
|
|
int i, j, k;
|
|
|
|
/* There should be three types. */
|
|
if (nc_inq_typeids(ncid, &ntypes_in, typeids_in)) ERR;
|
|
if (ntypes_in != THREE_TYPES) ERR;
|
|
|
|
/* The s1 compound type is first: check it out. */
|
|
if (nc_inq_compound(ncid, typeids_in[0], name_in, &size_in, &nfields_in)) ERR;
|
|
if (nfields_in != 2 || strcmp(name_in, S1_TYPE_NAME) || size_in != sizeof(struct s1)) ERR;
|
|
if (nc_inq_compound_field(ncid, typeids_in[0], 0, name_in, &offset_in,
|
|
&field_type_in, &ndims_in, NULL)) ERR;
|
|
if (strcmp(name_in, X_NAME) || offset_in != 0 || field_type_in != NC_FLOAT ||
|
|
ndims_in) ERR;
|
|
if (nc_inq_compound_field(ncid, typeids_in[0], 1, name_in, &offset_in,
|
|
&field_type_in, &ndims_in, NULL)) ERR;
|
|
if (strcmp(name_in, Y_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s1, y) || field_type_in != NC_DOUBLE ||
|
|
ndims_in) ERR;
|
|
|
|
/* How does the vlen type look? */
|
|
if (nc_inq_vlen(ncid, typeids_in[1], name_in, &size_in, &base_nc_type_in)) ERR;
|
|
if (strcmp(name_in, VLEN_NAME) || size_in != sizeof(nc_vlen_t) ||
|
|
base_nc_type_in != typeids_in[0]) ERR;
|
|
|
|
/* How does the containing compound type look? */
|
|
if (nc_inq_compound(ncid, typeids_in[2], name_in, &size_in, &nfields_in)) ERR;
|
|
if (strcmp(name_in, S3_TYPE_NAME) || size_in != sizeof(struct s3) ||
|
|
nfields_in != 1) ERR;
|
|
if (nc_inq_compound_field(ncid, typeids_in[2], 0, name_in, &offset_in, &field_type_in,
|
|
&ndims_in, field_dims_in)) ERR;
|
|
if (strcmp(name_in, VL_NAME) || offset_in != NC_COMPOUND_OFFSET(struct s3, data) ||
|
|
field_type_in != typeids_in[1] || ndims_in != 1 || field_dims_in[0] != NUM_VL) ERR;
|
|
|
|
/* Now read the variable. */
|
|
if (nc_get_var(ncid, 0, data_in)) ERR;
|
|
|
|
/* Did we get the correct data? */
|
|
for (i = 0; i < DIM3_LEN; i++)
|
|
for (j = 0; j < NUM_VL; j++)
|
|
{
|
|
if (data_in[i].data[j].len != data_out[i].data[j].len) ERR;
|
|
for (k = 0; k < data_out[i].data[j].len; k++)
|
|
if (((struct s1 *)data_in[i].data[j].p)[k].x != ((struct s1 *)data_out[i].data[j].p)[k].x ||
|
|
((struct s1 *)data_in[i].data[j].p)[k].y != ((struct s1 *)data_out[i].data[j].p)[k].y) ERR;
|
|
}
|
|
|
|
/* Free our vlens. */
|
|
for (i = 0; i < DIM3_LEN; i++)
|
|
for (j = 0; j < NUM_VL; j++)
|
|
nc_free_vlen(&(data_in[i].data[j]));
|
|
|
|
/* We're done! */
|
|
return NC_NOERR;
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
int ncid;
|
|
int i, j, k;
|
|
nc_vlen_t *vlen_of_comp_out;
|
|
struct s2 *comp_array_of_comp_out;
|
|
struct s3 *comp_array_of_vlen_of_comp_out;
|
|
|
|
printf("\nTesting nested types across platforms.\n");
|
|
|
|
if (!(vlen_of_comp_out = calloc(sizeof(nc_vlen_t), DIM1_LEN))) ERR;
|
|
if (!(comp_array_of_comp_out = calloc(sizeof(struct s2), DIM2_LEN))) ERR;
|
|
if (!(comp_array_of_vlen_of_comp_out = calloc(sizeof(struct s3), DIM3_LEN))) ERR;
|
|
|
|
/* Create some output data: a vlen of struct s1. */
|
|
for (size_t i = 0; i < DIM1_LEN; i++)
|
|
{
|
|
vlen_of_comp_out[i].len = i + 1;
|
|
if (!(vlen_of_comp_out[i].p = malloc(sizeof(struct s1) * vlen_of_comp_out[i].len)))
|
|
return NC_ENOMEM;
|
|
for (j = 0; j < vlen_of_comp_out[i].len; j++)
|
|
{
|
|
((struct s1 *)vlen_of_comp_out[i].p)[j].x = 42.42f;
|
|
((struct s1 *)vlen_of_comp_out[i].p)[j].y = 2.0;
|
|
}
|
|
}
|
|
|
|
/* Create some output data: a struct which holds an array of
|
|
* struct s1. */
|
|
for (i = 0; i < DIM2_LEN; i++)
|
|
for (j = 0; j < NUM_S1; j++)
|
|
{
|
|
comp_array_of_comp_out[i].data[j].x = 42.42f;
|
|
comp_array_of_comp_out[i].data[j].y = 2.0;
|
|
}
|
|
|
|
/* Create some output data: a struct which holds an array of
|
|
* vlen of struct s1. */
|
|
for (size_t i = 0; i < DIM3_LEN; i++)
|
|
for (j = 0; j < NUM_VL; j++)
|
|
{
|
|
comp_array_of_vlen_of_comp_out[i].data[j].len = i + 1;
|
|
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)))
|
|
return NC_ENOMEM;
|
|
for (k = 0; k < comp_array_of_vlen_of_comp_out[i].data[j].len; k++)
|
|
{
|
|
((struct s1 *)comp_array_of_vlen_of_comp_out[i].data[j].p)[k].x = 42.42f;
|
|
((struct s1 *)comp_array_of_vlen_of_comp_out[i].data[j].p)[k].y = 2.0;
|
|
}
|
|
}
|
|
|
|
printf("*** testing of vlen of compound type...");
|
|
{
|
|
nc_type s1_typeid, vlen_typeid;
|
|
|
|
/* Create a netCDF-4 file. */
|
|
if (nc_create(FILE_NAME_1, NC_NETCDF4, &ncid)) ERR;
|
|
|
|
/* Create a simple compound type which has different sizes on
|
|
* different platforms - our old friend struct s1. */
|
|
if (nc_def_compound(ncid, sizeof(struct s1), S1_TYPE_NAME, &s1_typeid)) ERR;
|
|
if (nc_insert_compound(ncid, s1_typeid, X_NAME,
|
|
NC_COMPOUND_OFFSET(struct s1, x), NC_FLOAT)) ERR;
|
|
if (nc_insert_compound(ncid, s1_typeid, Y_NAME,
|
|
NC_COMPOUND_OFFSET(struct s1, y), NC_DOUBLE)) ERR;
|
|
|
|
/* Now make a new type: a vlen of our compound type. */
|
|
if (nc_def_vlen(ncid, VLEN_NAME, s1_typeid, &vlen_typeid)) ERR;
|
|
|
|
/* Write the output data as an attribute. */
|
|
if (nc_put_att(ncid, NC_GLOBAL, VLEN_ATT_NAME, vlen_typeid,
|
|
DIM1_LEN, vlen_of_comp_out)) ERR;
|
|
|
|
/* How does it look? */
|
|
if (check_file_1(ncid, vlen_of_comp_out)) ERR;
|
|
|
|
/* We're done - wasn't that easy? */
|
|
if (nc_close(ncid)) ERR;
|
|
|
|
/* Check it out. */
|
|
if (nc_open(FILE_NAME_1, NC_NOWRITE, &ncid)) ERR;
|
|
if (check_file_1(ncid, vlen_of_comp_out)) ERR;
|
|
if (nc_close(ncid)) ERR;
|
|
}
|
|
SUMMARIZE_ERR;
|
|
printf("*** testing Solaris-written vlen of compound type...");
|
|
{
|
|
char file_in[NC_MAX_NAME + 1];
|
|
|
|
strcpy(file_in, "");
|
|
if (getenv("srcdir"))
|
|
{
|
|
strcat(file_in, getenv("srcdir"));
|
|
strcat(file_in, "/");
|
|
}
|
|
strcat(file_in, REF_FILE_NAME_1);
|
|
|
|
/* Check out the same file, generated on buddy and included with
|
|
* the distribution. */
|
|
if (nc_open(file_in, NC_NOWRITE, &ncid)) ERR;
|
|
if (check_file_1(ncid, vlen_of_comp_out)) ERR;
|
|
if (nc_close(ncid)) ERR;
|
|
}
|
|
SUMMARIZE_ERR;
|
|
printf("*** testing compound type containing array of compound type...");
|
|
{
|
|
nc_type s1_typeid, s2_typeid;
|
|
int dimsizes[1] = {NUM_S1};
|
|
|
|
/* Create a netCDF-4 file. */
|
|
if (nc_create(FILE_NAME_2, NC_NETCDF4, &ncid)) ERR;
|
|
|
|
/* Create a simple compound type which has different sizes on
|
|
* different platforms - our old friend struct s1. */
|
|
if (nc_def_compound(ncid, sizeof(struct s1), S1_TYPE_NAME, &s1_typeid)) ERR;
|
|
if (nc_insert_compound(ncid, s1_typeid, X_NAME,
|
|
NC_COMPOUND_OFFSET(struct s1, x), NC_FLOAT)) ERR;
|
|
if (nc_insert_compound(ncid, s1_typeid, Y_NAME,
|
|
NC_COMPOUND_OFFSET(struct s1, y), NC_DOUBLE)) ERR;
|
|
|
|
/* Now make a compound type that holds an array of the struct s1
|
|
* type. */
|
|
if (nc_def_compound(ncid, sizeof(struct s2), S2_TYPE_NAME, &s2_typeid)) ERR;
|
|
if (nc_insert_array_compound(ncid, s2_typeid, S1_NAME,
|
|
NC_COMPOUND_OFFSET(struct s2, data),
|
|
s1_typeid, 1, dimsizes)) ERR;
|
|
|
|
|
|
/* Write the output data as an attribute. */
|
|
if (nc_put_att(ncid, NC_GLOBAL, S2_ATT_NAME, s2_typeid,
|
|
DIM2_LEN, comp_array_of_comp_out)) ERR;
|
|
|
|
/* How does it look? */
|
|
if (check_file_2(ncid, comp_array_of_comp_out)) ERR;
|
|
|
|
/* We're done - wasn't that easy? */
|
|
if (nc_close(ncid)) ERR;
|
|
|
|
/* Check it out. */
|
|
if (nc_open(FILE_NAME_2, NC_NOWRITE, &ncid)) ERR;
|
|
if (check_file_2(ncid, comp_array_of_comp_out)) ERR;
|
|
if (nc_close(ncid)) ERR;
|
|
}
|
|
SUMMARIZE_ERR;
|
|
printf("*** testing Solaris-written compound type containing array of compound type...");
|
|
{
|
|
char file_in[NC_MAX_NAME + 1];
|
|
|
|
strcpy(file_in, "");
|
|
if (getenv("srcdir"))
|
|
{
|
|
strcat(file_in, getenv("srcdir"));
|
|
strcat(file_in, "/");
|
|
}
|
|
strcat(file_in, REF_FILE_NAME_2);
|
|
|
|
/* Check out the same file, generated on buddy and included with
|
|
* the distribution. */
|
|
if (nc_open(file_in, NC_NOWRITE, &ncid)) ERR;
|
|
if (check_file_2(ncid, comp_array_of_comp_out)) ERR;
|
|
if (nc_close(ncid)) ERR;
|
|
}
|
|
SUMMARIZE_ERR;
|
|
printf("*** testing compound attribute containing array of vlen of compound type...");
|
|
{
|
|
nc_type vlen_typeid, s3_typeid, s1_typeid;
|
|
int dimsizes[1] = {NUM_VL};
|
|
|
|
/* Create a netCDF-4 file. */
|
|
if (nc_create(FILE_NAME_3, NC_NETCDF4, &ncid)) ERR;
|
|
|
|
/* Create a simple compound type which has different sizes on
|
|
* different platforms - our old friend struct s1. */
|
|
if (nc_def_compound(ncid, sizeof(struct s1), S1_TYPE_NAME, &s1_typeid)) ERR;
|
|
if (nc_insert_compound(ncid, s1_typeid, X_NAME,
|
|
NC_COMPOUND_OFFSET(struct s1, x), NC_FLOAT)) ERR;
|
|
if (nc_insert_compound(ncid, s1_typeid, Y_NAME,
|
|
NC_COMPOUND_OFFSET(struct s1, y), NC_DOUBLE)) ERR;
|
|
|
|
/* Now make a new type: a vlen of our s1 compound type. */
|
|
if (nc_def_vlen(ncid, VLEN_NAME, s1_typeid, &vlen_typeid)) ERR;
|
|
|
|
/* Now make a compound type that holds an array of the VLEN
|
|
* type. */
|
|
if (nc_def_compound(ncid, sizeof(struct s3), S3_TYPE_NAME, &s3_typeid)) ERR;
|
|
if (nc_insert_array_compound(ncid, s3_typeid, VL_NAME,
|
|
NC_COMPOUND_OFFSET(struct s3, data),
|
|
vlen_typeid, 1, dimsizes)) ERR;
|
|
|
|
|
|
/* Write the output data as an attribute. */
|
|
if (nc_put_att(ncid, NC_GLOBAL, S3_ATT_NAME, s3_typeid,
|
|
DIM3_LEN, comp_array_of_vlen_of_comp_out)) ERR;
|
|
|
|
/* How does it look? Uncomment this line to see memory issue. */
|
|
/* if (check_file_3(ncid, comp_array_of_vlen_of_comp_out)) ERR; */
|
|
|
|
/* We're done - wasn't that easy? */
|
|
if (nc_close(ncid)) ERR;
|
|
|
|
/* Check it out. */
|
|
if (nc_open(FILE_NAME_3, NC_NOWRITE, &ncid)) ERR;
|
|
if (check_file_3(ncid, comp_array_of_vlen_of_comp_out)) ERR;
|
|
if (nc_close(ncid)) ERR;
|
|
}
|
|
SUMMARIZE_ERR;
|
|
printf("*** testing compound variable containing array of vlen of compound type...");
|
|
{
|
|
nc_type vlen_typeid, s3_typeid, s1_typeid;
|
|
int varid, dimid;
|
|
int dimsizes[1] = {NUM_VL};
|
|
|
|
/* Create a netCDF-4 file. */
|
|
if (nc_create(FILE_NAME_4, NC_NETCDF4, &ncid)) ERR;
|
|
|
|
/* Create a simple compound type which has different sizes on
|
|
* different platforms - our old friend struct s1. */
|
|
if (nc_def_compound(ncid, sizeof(struct s1), S1_TYPE_NAME, &s1_typeid)) ERR;
|
|
if (nc_insert_compound(ncid, s1_typeid, X_NAME,
|
|
NC_COMPOUND_OFFSET(struct s1, x), NC_FLOAT)) ERR;
|
|
if (nc_insert_compound(ncid, s1_typeid, Y_NAME,
|
|
NC_COMPOUND_OFFSET(struct s1, y), NC_DOUBLE)) ERR;
|
|
|
|
/* Now make a new type: a vlen of our s1 compound type. */
|
|
if (nc_def_vlen(ncid, VLEN_NAME, s1_typeid, &vlen_typeid)) ERR;
|
|
|
|
/* Now make a compound type that holds an array of the VLEN
|
|
* type. */
|
|
if (nc_def_compound(ncid, sizeof(struct s3), S3_TYPE_NAME, &s3_typeid)) ERR;
|
|
if (nc_insert_array_compound(ncid, s3_typeid, VL_NAME,
|
|
NC_COMPOUND_OFFSET(struct s3, data),
|
|
vlen_typeid, 1, dimsizes)) ERR;
|
|
|
|
/* Create a dimension and a var of s3 type, then write the
|
|
* data. */
|
|
if (nc_def_dim(ncid, DIM3_NAME, DIM3_LEN, &dimid)) ERR;
|
|
if (nc_def_var(ncid, VAR3_NAME, s3_typeid, 1, &dimid, &varid)) ERR;
|
|
if (nc_put_var(ncid, varid, comp_array_of_vlen_of_comp_out)) ERR;
|
|
|
|
/* How does it look? */
|
|
if (check_file_4(ncid, comp_array_of_vlen_of_comp_out)) ERR;
|
|
|
|
/* We're done - wasn't that easy? */
|
|
if (nc_close(ncid)) ERR;
|
|
|
|
/* Check it out. */
|
|
if (nc_open(FILE_NAME_4, NC_NOWRITE, &ncid)) ERR;
|
|
if (check_file_4(ncid, comp_array_of_vlen_of_comp_out)) ERR;
|
|
if (nc_close(ncid)) ERR;
|
|
}
|
|
SUMMARIZE_ERR;
|
|
|
|
/* Free our mallocs. */
|
|
for (i = 0; i < DIM1_LEN; i++)
|
|
free(vlen_of_comp_out[i].p);
|
|
for (i = 0; i < DIM3_LEN; i++)
|
|
for (j = 0; j < NUM_VL; j++)
|
|
free(comp_array_of_vlen_of_comp_out[i].data[j].p);
|
|
|
|
free(comp_array_of_comp_out);
|
|
free(comp_array_of_vlen_of_comp_out);
|
|
free(vlen_of_comp_out);
|
|
|
|
/* Now run the tests formerly in tst_h_atts2.c. */
|
|
#define REF_FILE_NAME "tst_xplatform2_3.nc"
|
|
#define NUM_OBJ 3
|
|
|
|
printf("\n*** Checking HDF5 attribute functions some more.\n");
|
|
printf("*** Opening tst_xplatform2_3.nc...");
|
|
{
|
|
hid_t fileid, grpid, attid;
|
|
hid_t file_typeid1[NUM_OBJ], native_typeid1[NUM_OBJ];
|
|
hid_t file_typeid2, native_typeid2;
|
|
hsize_t num_obj, i;
|
|
#if H5_VERSION_GE(1,12,0)
|
|
H5O_info2_t obj_info;
|
|
#else
|
|
H5O_info_t obj_info;
|
|
#endif
|
|
char obj_name[NC_MAX_NAME + 1];
|
|
|
|
/* Open one of the netCDF test files. */
|
|
if ((fileid = H5Fopen(REF_FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
|
|
if ((grpid = H5Gopen1(fileid, "/")) < 0) ERR;
|
|
|
|
/* How many objects in this group? */
|
|
if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
|
|
if (num_obj != NUM_OBJ) ERR;
|
|
|
|
/* For each object in the group... */
|
|
for (i = 0; i < num_obj; i++)
|
|
{
|
|
/* Get the name. */
|
|
#if H5_VERSION_GE(1,12,0)
|
|
if (H5Oget_info_by_idx3(grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC,
|
|
i, &obj_info, H5O_INFO_BASIC, H5P_DEFAULT) < 0) ERR_RET;
|
|
#else
|
|
if (H5Oget_info_by_idx(grpid, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC,
|
|
i, &obj_info, H5P_DEFAULT) < 0) ERR_RET;
|
|
#endif
|
|
if (H5Lget_name_by_idx(grpid, ".", H5_INDEX_NAME, H5_ITER_INC, i,
|
|
obj_name, NC_MAX_NAME + 1, H5P_DEFAULT) < 0) ERR_RET;
|
|
printf(" reading type %s ", obj_name);
|
|
if (obj_info.type != H5O_TYPE_NAMED_DATATYPE) ERR_RET;
|
|
|
|
/* Get the typeid. */
|
|
if ((file_typeid1[i] = H5Topen2(grpid, obj_name, H5P_DEFAULT)) < 0) ERR_RET;
|
|
if ((native_typeid1[i] = H5Tget_native_type(file_typeid1[i], H5T_DIR_DEFAULT)) < 0) ERR_RET;
|
|
}
|
|
|
|
/* There is one att: open it by index. */
|
|
if ((attid = H5Aopen_idx(grpid, 0)) < 0) ERR;
|
|
|
|
/* Get file and native typeids. */
|
|
if ((file_typeid2 = H5Aget_type(attid)) < 0) ERR;
|
|
if ((native_typeid2 = H5Tget_native_type(file_typeid2, H5T_DIR_DEFAULT)) < 0) ERR;
|
|
|
|
/* Close the attribute. */
|
|
if (H5Aclose(attid) < 0) ERR;
|
|
|
|
/* Close the typeids. */
|
|
if (H5Tclose(file_typeid2) < 0) ERR_RET;
|
|
if (H5Tclose(native_typeid2) < 0) ERR_RET;
|
|
for (i = 0; i < NUM_OBJ; i++)
|
|
{
|
|
if (H5Tclose(file_typeid1[i]) < 0) ERR_RET;
|
|
if (H5Tclose(native_typeid1[i]) < 0) ERR_RET;
|
|
}
|
|
|
|
/* Close the group and file. */
|
|
if (H5Gclose(grpid) < 0 ||
|
|
H5Fclose(fileid) < 0) ERR;
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
printf("*** Opening tst_xplatform2_3.nc again...");
|
|
{
|
|
hid_t fileid, grpid, attid, file_typeid, native_typeid;
|
|
hid_t file_typeid2, native_typeid2;
|
|
|
|
/* Open one of the netCDF test files. */
|
|
if ((fileid = H5Fopen(REF_FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
|
|
if ((grpid = H5Gopen1(fileid, "/")) < 0) ERR;
|
|
|
|
/* There is one att: open it by index. */
|
|
if ((attid = H5Aopen_idx(grpid, 0)) < 0) ERR;
|
|
|
|
/* Get file and native typeids. */
|
|
if ((file_typeid = H5Aget_type(attid)) < 0) ERR;
|
|
if ((native_typeid = H5Tget_native_type(file_typeid, H5T_DIR_DEFAULT)) < 0) ERR;
|
|
|
|
/* Now getting another copy of the native typeid will fail! WTF? */
|
|
if ((file_typeid2 = H5Aget_type(attid)) < 0) ERR;
|
|
if ((native_typeid2 = H5Tget_native_type(file_typeid, H5T_DIR_DEFAULT)) < 0) ERR;
|
|
|
|
/* Close the attribute. */
|
|
if (H5Aclose(attid) < 0) ERR;
|
|
|
|
/* Close the typeids. */
|
|
if (H5Tclose(file_typeid) < 0) ERR;
|
|
if (H5Tclose(native_typeid) < 0) ERR;
|
|
if (H5Tclose(file_typeid2) < 0) ERR;
|
|
if (H5Tclose(native_typeid2) < 0) ERR;
|
|
|
|
/* Close the group and file. */
|
|
if (H5Gclose(grpid) < 0 ||
|
|
H5Fclose(fileid) < 0) ERR;
|
|
}
|
|
SUMMARIZE_ERR;
|
|
FINAL_RESULTS;
|
|
}
|