netcdf-c/h5_test/tst_h_strings.c
2021-04-28 13:59:24 -06:00

341 lines
11 KiB
C

/* This is part of the netCDF package. Copyright 2018 University
Corporation for Atmospheric Research/Unidata See COPYRIGHT file for
conditions of use.
This program does HDF5 string stuff.
Here's a HDF5 sample programs:
http://hdf.ncsa.uiuc.edu/training/other-ex5/sample-programs/strings.c
*/
#include <string.h>
#include "h5_err_macros.h"
#include <hdf5.h>
#define FILE_NAME "tst_h_strings.h5"
#define DIM1_LEN 3
#define ATT_NAME "Stooge_Statements"
#define GRP_NAME "Stooge_Antic_Metrics"
int
main()
{
printf("\n*** Checking HDF5 string types.\n");
printf("*** Checking scalar string attribute...");
{
hid_t fileid, grpid, spaceid, typeid, attid;
hid_t class;
size_t type_size;
htri_t is_str;
const char *data = "The art of war is of vital "
"importance to the State. It is a matter of life and death, a road either"
"to safety or to ruin. Hence it is a subject of inquiry"
"which can on no account be neglected.";
char *data_in = NULL;
/* Open file. */
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
H5P_DEFAULT)) < 0) ERR;
if ((grpid = H5Gcreate1(fileid, GRP_NAME, 0)) < 0) ERR;
/* Create string type. */
if ((typeid = H5Tcopy(H5T_C_S1)) < 0) ERR;
if (H5Tset_size(typeid, H5T_VARIABLE) < 0) ERR;
/* Write an attribute of this type. */
if ((spaceid = H5Screate(H5S_SCALAR)) < 0) ERR;
if ((attid = H5Acreate1(grpid, ATT_NAME, typeid, spaceid,
H5P_DEFAULT)) < 0) ERR;
if (H5Awrite(attid, typeid, &data) < 0) ERR;
/* Close up. */
if (H5Aclose(attid) < 0) ERR;
if (H5Tclose(typeid) < 0) ERR;
if (H5Sclose(spaceid) < 0) ERR;
if (H5Gclose(grpid) < 0) ERR;
if (H5Fclose(fileid) < 0) ERR;
/* Now reopen the file and check it out. */
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
if ((grpid = H5Gopen1(fileid, GRP_NAME)) < 0) ERR;
if ((attid = H5Aopen_name(grpid, ATT_NAME)) < 0) ERR;
if ((typeid = H5Aget_type(attid)) < 0) ERR;
if ((spaceid = H5Aget_space(attid)) < 0) ERR;
/* Given this type id, how would we know this is a string
* attribute? */
if ((class = H5Tget_class(typeid)) < 0) ERR;
if (class != H5T_STRING) ERR;
if (!(type_size = H5Tget_size(typeid))) ERR;
if (type_size != sizeof(char *)) ERR;
if ((is_str = H5Tis_variable_str(typeid)) < 0) ERR;
if (!is_str) ERR;
/* Make sure this is a scalar. */
if (H5Sget_simple_extent_type(spaceid) != H5S_SCALAR) ERR;
/* Read the attribute. */
if (H5Aread(attid, typeid, &data_in) < 0) ERR;
/* Check the data. */
if (strcmp(data, data_in)) ERR;
/* Free the memory returned by H5Aread */
free(data_in);
/* Close HDF5 stuff. */
if (H5Aclose(attid) < 0) ERR;
if (H5Tclose(typeid) < 0) ERR;
if (H5Sclose(spaceid) < 0) ERR;
if (H5Gclose(grpid) < 0) ERR;
if (H5Fclose(fileid) < 0) ERR;
}
SUMMARIZE_ERR;
printf("*** Checking simple HDF5 string types...");
{
hid_t fileid, grpid, spaceid, typeid, attid;
hsize_t dims[1] = {DIM1_LEN};
/* size_t type_size;
htri_t is_str;*/
hid_t class;
char *data[DIM1_LEN] = {"Ohhh!", "Ahhh!", "Wub-wub-wub!"};
char **data_in;
int i;
/* Open file. */
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
H5P_DEFAULT)) < 0) ERR;
if ((grpid = H5Gcreate1(fileid, GRP_NAME, 0)) < 0) ERR;
/* Create string type. */
if ((typeid = H5Tcopy(H5T_C_S1)) < 0) ERR;
if (H5Tset_size(typeid, H5T_VARIABLE) < 0) ERR;
/* I thought the following should work instead of the H5Tcopy and
* H5Tset_size functions above, but it doesn't. */
/*if ((typeid = H5Tvlen_create(H5T_NATIVE_CHAR)) < 0) ERR;*/
/* Write an attribute of this (string) type. */
if ((spaceid = H5Screate_simple(1, dims, NULL)) < 0) ERR;
if ((attid = H5Acreate1(grpid, ATT_NAME, typeid, spaceid,
H5P_DEFAULT)) < 0) ERR;
if (H5Awrite(attid, typeid, data) < 0) ERR;
if (H5Aclose(attid) < 0) ERR;
if (H5Tclose(typeid) < 0) ERR;
if (H5Gclose(grpid) < 0) ERR;
if (H5Fclose(fileid) < 0) ERR;
/* Now reopen the file and check it out. */
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
if ((grpid = H5Gopen1(fileid, GRP_NAME)) < 0) ERR;
if ((attid = H5Aopen_name(grpid, ATT_NAME)) < 0) ERR;
if ((typeid = H5Aget_type(attid)) < 0) ERR;
/* Given this type id, how would we know this is a string
* attribute? */
if ((class = H5Tget_class(typeid)) < 0) ERR;
if (class != H5T_STRING) ERR;
/* if (!(type_size = H5Tget_size(typeid))) ERR;
if ((is_str = H5Tis_variable_str(typeid)) < 0) ERR;*/
/* How many strings are in the string array? */
if ((spaceid = H5Aget_space(attid)) < 0) ERR;
if (H5Sget_simple_extent_dims(spaceid, dims, NULL) < 0) ERR;
if (!(data_in = malloc(dims[0] * sizeof(char *)))) ERR;
/* Now read the array of strings. The HDF5 library will allocate
* space for each string. */
if (H5Aread(attid, typeid, data_in) < 0) ERR;
/* Compare the values to make sure it worked... */
for (i = 0; i < DIM1_LEN; i++)
if (strcmp(data[i], data_in[i])) ERR;
/* Free the memory that HDF5 allocated. */
for (i = 0; i < DIM1_LEN; i++)
free(data_in[i]);
/* Free the memory that we allocated. */
free(data_in);
/* Close everything up. */
if (H5Aclose(attid) < 0) ERR;
if (H5Tclose(typeid) < 0) ERR;
if (H5Gclose(grpid) < 0) ERR;
if (H5Fclose(fileid) < 0) ERR;
}
SUMMARIZE_ERR;
printf("*** Checking G&S compliance...");
{
#define S1 "When Frederick was a little lad"
#define S2 "He proved so brave and daring..."
char **data;
char **data_in;
hsize_t dims_in[1], dims[1] = {2};
hid_t fileid, grpid, spaceid, typeid, attid;
hid_t class;
int i;
/* Allocate space and copy strings. */
data = malloc(sizeof(char *) * 2);
data[0] = malloc(strlen(S1) + 1);
strcpy(data[0], S1);
data[1] = malloc(strlen(S2) + 1);
strcpy(data[1], S2);
/* Open file. */
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
H5P_DEFAULT)) < 0) ERR;
if ((grpid = H5Gcreate1(fileid, GRP_NAME, 0)) < 0) ERR;
/* Create string type. */
if ((typeid = H5Tcopy(H5T_C_S1)) < 0) ERR;
if (H5Tset_size(typeid, H5T_VARIABLE) < 0) ERR;
/* I thought the following should work instead of the H5Tcopy and
* H5Tset_size functions above, but it doesn't. */
/*if ((typeid = H5Tvlen_create(H5T_NATIVE_CHAR)) < 0) ERR;*/
/* Write an attribute of this type. */
if ((spaceid = H5Screate_simple(1, dims, NULL)) < 0) ERR;
if ((attid = H5Acreate1(grpid, ATT_NAME, typeid, spaceid,
H5P_DEFAULT)) < 0) ERR;
if (H5Awrite(attid, typeid, data) < 0) ERR;
/* Close up. */
if (H5Aclose(attid) < 0) ERR;
if (H5Tclose(typeid) < 0) ERR;
if (H5Gclose(grpid) < 0) ERR;
if (H5Fclose(fileid) < 0) ERR;
/* Now reopen the file and check it out. */
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
if ((grpid = H5Gopen1(fileid, GRP_NAME)) < 0) ERR;
if ((attid = H5Aopen_name(grpid, ATT_NAME)) < 0) ERR;
if ((typeid = H5Aget_type(attid)) < 0) ERR;
/* Given this type id, how would we know this is a string
* attribute? */
if ((class = H5Tget_class(typeid)) < 0) ERR;
if (class != H5T_STRING) ERR;
/* How many strings are in the array? */
if (H5Sget_simple_extent_dims(spaceid, dims_in, NULL) != 1) ERR;
if (dims_in[0] != dims[0]) ERR;
/* Allocate enough pointers to read the data. The HDF5 library
* will allocate the space needed for each string. */
if (!(data_in = malloc(dims_in[0] * sizeof(char *)))) ERR;
/* Read the data. */
if (H5Aread(attid, typeid, data_in) < 0) ERR;
/* Check the data. */
for (i = 0; i < 2; i++)
if (strcmp(data[i], data_in[i])) ERR;
/* Free our memory. */
for (i = 0; i < 2; i++)
free(data_in[i]);
free(data_in);
free(data[0]);
free(data[1]);
free(data);
/* Close HDF5 stuff. */
if (H5Aclose(attid) < 0) ERR;
if (H5Tclose(typeid) < 0) ERR;
if (H5Gclose(grpid) < 0) ERR;
if (H5Fclose(fileid) < 0) ERR;
}
SUMMARIZE_ERR;
printf("*** Checking empty strings...");
{
char **data;
char **data_in;
hsize_t dims_in[1], dims[1] = {2};
hid_t fileid, grpid, spaceid, typeid, attid;
hid_t class;
int i;
/* Allocate space and copy strings. */
data = malloc(sizeof(char *) * 2);
data[0] = malloc(strlen(S1) + 1);
strcpy(data[0], "");
data[1] = malloc(strlen(S2) + 1);
strcpy(data[1], "");
/* Open file. */
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
H5P_DEFAULT)) < 0) ERR;
if ((grpid = H5Gcreate1(fileid, GRP_NAME, 0)) < 0) ERR;
/* Create string type. */
if ((typeid = H5Tcopy(H5T_C_S1)) < 0) ERR;
if (H5Tset_size(typeid, H5T_VARIABLE) < 0) ERR;
/* I thought the following should work instead of the H5Tcopy and
* H5Tset_size functions above, but it doesn't. */
/*if ((typeid = H5Tvlen_create(H5T_NATIVE_CHAR)) < 0) ERR;*/
/* Write an attribute of this type. */
if ((spaceid = H5Screate_simple(1, dims, NULL)) < 0) ERR;
if ((attid = H5Acreate1(grpid, ATT_NAME, typeid, spaceid,
H5P_DEFAULT)) < 0) ERR;
if (H5Awrite(attid, typeid, data) < 0) ERR;
/* Close up. */
if (H5Aclose(attid) < 0) ERR;
if (H5Tclose(typeid) < 0) ERR;
if (H5Gclose(grpid) < 0) ERR;
if (H5Fclose(fileid) < 0) ERR;
/* Now reopen the file and check it out. */
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
if ((grpid = H5Gopen1(fileid, GRP_NAME)) < 0) ERR;
if ((attid = H5Aopen_name(grpid, ATT_NAME)) < 0) ERR;
if ((typeid = H5Aget_type(attid)) < 0) ERR;
/* Given this type id, how would we know this is a string
* attribute? */
if ((class = H5Tget_class(typeid)) < 0) ERR;
if (class != H5T_STRING) ERR;
/* How many strings are in the array? */
if (H5Sget_simple_extent_dims(spaceid, dims_in, NULL) != 1) ERR;
if (dims_in[0] != dims[0]) ERR;
/* Allocate enough pointers to read the data. The HDF5 library
* will allocate the space needed for each string. */
if (!(data_in = malloc(dims_in[0] * sizeof(char *)))) ERR;
/* Read the data. */
if (H5Aread(attid, typeid, data_in) < 0) ERR;
/* Check the data. */
for (i = 0; i < 2; i++)
if (strcmp(data[i], data_in[i])) ERR;
/* Free our memory. */
for (i = 0; i < 2; i++)
free(data_in[i]);
free(data_in);
free(data[0]);
free(data[1]);
free(data);
/* Close HDF5 stuff. */
if (H5Aclose(attid) < 0) ERR;
if (H5Tclose(typeid) < 0) ERR;
if (H5Gclose(grpid) < 0) ERR;
if (H5Fclose(fileid) < 0) ERR;
}
SUMMARIZE_ERR;
FINAL_RESULTS;
}