mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-11-27 07:30:33 +08:00
341 lines
11 KiB
C
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;
|
|
}
|