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.
4
5 This program does HDF5 string stuff.
6
7 Here's a HDF5 sample programs:
8 http://hdf.ncsa.uiuc.edu/training/other-ex5/sample-programs/strings.c
9 */
10 #include <string.h>
11 #include "h5_err_macros.h"
12 #include <hdf5.h>
13
14 #define FILE_NAME "tst_h_strings.h5"
15 #define DIM1_LEN 3
16 #define ATT_NAME "Stooge_Statements"
17 #define GRP_NAME "Stooge_Antic_Metrics"
18
19 int
main()20 main()
21 {
22 printf("\n*** Checking HDF5 string types.\n");
23 printf("*** Checking scalar string attribute...");
24 {
25 hid_t fileid, grpid, spaceid, typeid, attid;
26 hid_t class;
27 size_t type_size;
28 htri_t is_str;
29
30 const char *data = "The art of war is of vital "
31 "importance to the State. It is a matter of life and death, a road either"
32 "to safety or to ruin. Hence it is a subject of inquiry"
33 "which can on no account be neglected.";
34
35 char *data_in = NULL;
36
37 /* Open file. */
38 if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
39 H5P_DEFAULT)) < 0) ERR;
40 if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
41
42 /* Create string type. */
43 if ((typeid = H5Tcopy(H5T_C_S1)) < 0) ERR;
44 if (H5Tset_size(typeid, H5T_VARIABLE) < 0) ERR;
45
46 /* Write an attribute of this type. */
47 if ((spaceid = H5Screate(H5S_SCALAR)) < 0) ERR;
48 if ((attid = H5Acreate(grpid, ATT_NAME, typeid, spaceid,
49 H5P_DEFAULT)) < 0) ERR;
50 if (H5Awrite(attid, typeid, &data) < 0) ERR;
51
52 /* Close up. */
53 if (H5Aclose(attid) < 0) ERR;
54 if (H5Tclose(typeid) < 0) ERR;
55 if (H5Sclose(spaceid) < 0) ERR;
56 if (H5Gclose(grpid) < 0) ERR;
57 if (H5Fclose(fileid) < 0) ERR;
58
59 /* Now reopen the file and check it out. */
60 if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
61 if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
62 if ((attid = H5Aopen_name(grpid, ATT_NAME)) < 0) ERR;
63 if ((typeid = H5Aget_type(attid)) < 0) ERR;
64 if ((spaceid = H5Aget_space(attid)) < 0) ERR;
65
66 /* Given this type id, how would we know this is a string
67 * attribute? */
68 if ((class = H5Tget_class(typeid)) < 0) ERR;
69 if (class != H5T_STRING) ERR;
70 if (!(type_size = H5Tget_size(typeid))) ERR;
71 if (type_size != sizeof(char *)) ERR;
72 if ((is_str = H5Tis_variable_str(typeid)) < 0) ERR;
73 if (!is_str) ERR;
74
75 /* Make sure this is a scalar. */
76 if (H5Sget_simple_extent_type(spaceid) != H5S_SCALAR) ERR;
77
78 /* Read the attribute. */
79 if (H5Aread(attid, typeid, &data_in) < 0) ERR;
80
81 /* Check the data. */
82 if (strcmp(data, data_in)) ERR;
83
84 /* Free the memory returned by H5Aread */
85 free(data_in);
86
87 /* Close HDF5 stuff. */
88 if (H5Aclose(attid) < 0) ERR;
89 if (H5Tclose(typeid) < 0) ERR;
90 if (H5Sclose(spaceid) < 0) ERR;
91 if (H5Gclose(grpid) < 0) ERR;
92 if (H5Fclose(fileid) < 0) ERR;
93 }
94 SUMMARIZE_ERR;
95 printf("*** Checking simple HDF5 string types...");
96 {
97 hid_t fileid, grpid, spaceid, typeid, attid;
98 hsize_t dims[1] = {DIM1_LEN};
99 /* size_t type_size;
100 htri_t is_str;*/
101 hid_t class;
102 char *data[DIM1_LEN] = {"Ohhh!", "Ahhh!", "Wub-wub-wub!"};
103 char **data_in;
104 int i;
105
106 /* Open file. */
107 if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
108 H5P_DEFAULT)) < 0) ERR;
109 if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
110
111 /* Create string type. */
112 if ((typeid = H5Tcopy(H5T_C_S1)) < 0) ERR;
113 if (H5Tset_size(typeid, H5T_VARIABLE) < 0) ERR;
114
115 /* I thought the following should work instead of the H5Tcopy and
116 * H5Tset_size functions above, but it doesn't. */
117 /*if ((typeid = H5Tvlen_create(H5T_NATIVE_CHAR)) < 0) ERR;*/
118
119 /* Write an attribute of this (string) type. */
120 if ((spaceid = H5Screate_simple(1, dims, NULL)) < 0) ERR;
121 if ((attid = H5Acreate(grpid, ATT_NAME, typeid, spaceid,
122 H5P_DEFAULT)) < 0) ERR;
123 if (H5Awrite(attid, typeid, data) < 0) ERR;
124
125 if (H5Aclose(attid) < 0) ERR;
126 if (H5Tclose(typeid) < 0) ERR;
127 if (H5Gclose(grpid) < 0) ERR;
128 if (H5Fclose(fileid) < 0) ERR;
129
130 /* Now reopen the file and check it out. */
131 if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
132 if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
133 if ((attid = H5Aopen_name(grpid, ATT_NAME)) < 0) ERR;
134 if ((typeid = H5Aget_type(attid)) < 0) ERR;
135
136 /* Given this type id, how would we know this is a string
137 * attribute? */
138 if ((class = H5Tget_class(typeid)) < 0) ERR;
139 if (class != H5T_STRING) ERR;
140 /* if (!(type_size = H5Tget_size(typeid))) ERR;
141 if ((is_str = H5Tis_variable_str(typeid)) < 0) ERR;*/
142
143 /* How many strings are in the string array? */
144 if ((spaceid = H5Aget_space(attid)) < 0) ERR;
145 if (H5Sget_simple_extent_dims(spaceid, dims, NULL) < 0) ERR;
146 if (!(data_in = malloc(dims[0] * sizeof(char *)))) ERR;
147
148 /* Now read the array of strings. The HDF5 library will allocate
149 * space for each string. */
150 if (H5Aread(attid, typeid, data_in) < 0) ERR;
151
152 /* Compare the values to make sure it worked... */
153 for (i = 0; i < DIM1_LEN; i++)
154 if (strcmp(data[i], data_in[i])) ERR;
155
156 /* Free the memory that HDF5 allocated. */
157 for (i = 0; i < DIM1_LEN; i++)
158 free(data_in[i]);
159
160 /* Free the memory that we allocated. */
161 free(data_in);
162
163 /* Close everything up. */
164 if (H5Aclose(attid) < 0) ERR;
165 if (H5Tclose(typeid) < 0) ERR;
166 if (H5Gclose(grpid) < 0) ERR;
167 if (H5Fclose(fileid) < 0) ERR;
168 }
169
170 SUMMARIZE_ERR;
171 printf("*** Checking G&S compliance...");
172 {
173 #define S1 "When Frederick was a little lad"
174 #define S2 "He proved so brave and daring..."
175
176 char **data;
177 char **data_in;
178 hsize_t dims_in[1], dims[1] = {2};
179 hid_t fileid, grpid, spaceid, typeid, attid;
180 hid_t class;
181 int i;
182
183 /* Allocate space and copy strings. */
184 data = malloc(sizeof(char *) * 2);
185 data[0] = malloc(strlen(S1) + 1);
186 strcpy(data[0], S1);
187 data[1] = malloc(strlen(S2) + 1);
188 strcpy(data[1], S2);
189
190 /* Open file. */
191 if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
192 H5P_DEFAULT)) < 0) ERR;
193 if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
194
195 /* Create string type. */
196 if ((typeid = H5Tcopy(H5T_C_S1)) < 0) ERR;
197 if (H5Tset_size(typeid, H5T_VARIABLE) < 0) ERR;
198
199 /* I thought the following should work instead of the H5Tcopy and
200 * H5Tset_size functions above, but it doesn't. */
201 /*if ((typeid = H5Tvlen_create(H5T_NATIVE_CHAR)) < 0) ERR;*/
202
203 /* Write an attribute of this type. */
204 if ((spaceid = H5Screate_simple(1, dims, NULL)) < 0) ERR;
205 if ((attid = H5Acreate(grpid, ATT_NAME, typeid, spaceid,
206 H5P_DEFAULT)) < 0) ERR;
207 if (H5Awrite(attid, typeid, data) < 0) ERR;
208
209 /* Close up. */
210 if (H5Aclose(attid) < 0) ERR;
211 if (H5Tclose(typeid) < 0) ERR;
212 if (H5Gclose(grpid) < 0) ERR;
213 if (H5Fclose(fileid) < 0) ERR;
214
215 /* Now reopen the file and check it out. */
216 if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
217 if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
218 if ((attid = H5Aopen_name(grpid, ATT_NAME)) < 0) ERR;
219 if ((typeid = H5Aget_type(attid)) < 0) ERR;
220
221 /* Given this type id, how would we know this is a string
222 * attribute? */
223 if ((class = H5Tget_class(typeid)) < 0) ERR;
224 if (class != H5T_STRING) ERR;
225
226 /* How many strings are in the array? */
227 if (H5Sget_simple_extent_dims(spaceid, dims_in, NULL) != 1) ERR;
228 if (dims_in[0] != dims[0]) ERR;
229
230 /* Allocate enough pointers to read the data. The HDF5 library
231 * will allocate the space needed for each string. */
232 if (!(data_in = malloc(dims_in[0] * sizeof(char *)))) ERR;
233
234 /* Read the data. */
235 if (H5Aread(attid, typeid, data_in) < 0) ERR;
236
237 /* Check the data. */
238 for (i = 0; i < 2; i++)
239 if (strcmp(data[i], data_in[i])) ERR;
240
241 /* Free our memory. */
242 for (i = 0; i < 2; i++)
243 free(data_in[i]);
244 free(data_in);
245 free(data[0]);
246 free(data[1]);
247 free(data);
248
249 /* Close HDF5 stuff. */
250 if (H5Aclose(attid) < 0) ERR;
251 if (H5Tclose(typeid) < 0) ERR;
252 if (H5Gclose(grpid) < 0) ERR;
253 if (H5Fclose(fileid) < 0) ERR;
254 }
255
256 SUMMARIZE_ERR;
257 printf("*** Checking empty strings...");
258 {
259 char **data;
260 char **data_in;
261 hsize_t dims_in[1], dims[1] = {2};
262 hid_t fileid, grpid, spaceid, typeid, attid;
263 hid_t class;
264 int i;
265
266 /* Allocate space and copy strings. */
267 data = malloc(sizeof(char *) * 2);
268 data[0] = malloc(strlen(S1) + 1);
269 strcpy(data[0], "");
270 data[1] = malloc(strlen(S2) + 1);
271 strcpy(data[1], "");
272
273 /* Open file. */
274 if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
275 H5P_DEFAULT)) < 0) ERR;
276 if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
277
278 /* Create string type. */
279 if ((typeid = H5Tcopy(H5T_C_S1)) < 0) ERR;
280 if (H5Tset_size(typeid, H5T_VARIABLE) < 0) ERR;
281
282 /* I thought the following should work instead of the H5Tcopy and
283 * H5Tset_size functions above, but it doesn't. */
284 /*if ((typeid = H5Tvlen_create(H5T_NATIVE_CHAR)) < 0) ERR;*/
285
286 /* Write an attribute of this type. */
287 if ((spaceid = H5Screate_simple(1, dims, NULL)) < 0) ERR;
288 if ((attid = H5Acreate(grpid, ATT_NAME, typeid, spaceid,
289 H5P_DEFAULT)) < 0) ERR;
290 if (H5Awrite(attid, typeid, data) < 0) ERR;
291
292 /* Close up. */
293 if (H5Aclose(attid) < 0) ERR;
294 if (H5Tclose(typeid) < 0) ERR;
295 if (H5Gclose(grpid) < 0) ERR;
296 if (H5Fclose(fileid) < 0) ERR;
297
298 /* Now reopen the file and check it out. */
299 if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
300 if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
301 if ((attid = H5Aopen_name(grpid, ATT_NAME)) < 0) ERR;
302 if ((typeid = H5Aget_type(attid)) < 0) ERR;
303
304 /* Given this type id, how would we know this is a string
305 * attribute? */
306 if ((class = H5Tget_class(typeid)) < 0) ERR;
307 if (class != H5T_STRING) ERR;
308
309 /* How many strings are in the array? */
310 if (H5Sget_simple_extent_dims(spaceid, dims_in, NULL) != 1) ERR;
311 if (dims_in[0] != dims[0]) ERR;
312
313 /* Allocate enough pointers to read the data. The HDF5 library
314 * will allocate the space needed for each string. */
315 if (!(data_in = malloc(dims_in[0] * sizeof(char *)))) ERR;
316
317 /* Read the data. */
318 if (H5Aread(attid, typeid, data_in) < 0) ERR;
319
320 /* Check the data. */
321 for (i = 0; i < 2; i++)
322 if (strcmp(data[i], data_in[i])) ERR;
323
324 /* Free our memory. */
325 for (i = 0; i < 2; i++)
326 free(data_in[i]);
327 free(data_in);
328 free(data[0]);
329 free(data[1]);
330 free(data);
331
332 /* Close HDF5 stuff. */
333 if (H5Aclose(attid) < 0) ERR;
334 if (H5Tclose(typeid) < 0) ERR;
335 if (H5Gclose(grpid) < 0) ERR;
336 if (H5Fclose(fileid) < 0) ERR;
337 }
338 SUMMARIZE_ERR;
339 FINAL_RESULTS;
340 }
341