Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
H5FileIOLowLevel.c
Go to the documentation of this file.
1#include <config.h>
2
3#ifdef HAVE_HDF5
4/* FIXME: should really update interface */
5#define H5_USE_110_API
6#include <hdf5.h>
7#include <hdf5_hl.h>
8#endif
9
10#include <stdio.h>
11#include <string.h>
12#include <limits.h>
13#include <lal/LALStdio.h>
14#include <lal/LALStdlib.h>
15#include <lal/LALString.h>
16#include <lal/AVFactories.h>
17#include <lal/H5FileIO.h>
18
19/* INTERNAL */
20
21#ifdef __GNUC__
22#define UNUSED __attribute__ ((unused))
23#else
24#define UNUSED
25#endif
26
27#ifndef HAVE_HDF5
28#pragma GCC diagnostic ignored "-Wunused-parameter"
29#else
30
31/* replace HDF5 routines with threadsafe versions, if necessary */
32#include "H5ThreadSafe.c"
33
34#define LAL_H5_FILE_MODE_READ H5F_ACC_RDONLY
35#define LAL_H5_FILE_MODE_WRITE H5F_ACC_TRUNC
36
37struct tagLALH5Object {
38 hid_t object_id; /* this object's id must be first */
39};
40
41struct tagLALH5File {
42 hid_t file_id; /* this object's id must be first */
43 unsigned int mode;
44 int is_a_group;
45 char fname[FILENAME_MAX];
46};
47
48struct tagLALH5Dataset {
49 hid_t dataset_id; /* this object's id must be first */
50 hid_t parent_id;
51 hid_t space_id;
52 hid_t dtype_id; /* note: this is the in-memory type */
53 char name[]; /* flexible array member must be last */
54};
55
56/* creates HDF5 enum data type; use H5Tclose() to free */
57static hid_t XLALH5TypeEnum(const char *names[], const int values[], size_t length)
58{
59 hid_t dtype_id;
60 size_t i;
61 dtype_id = threadsafe_H5Tenum_create(H5T_NATIVE_INT);
62 if (dtype_id < 0)
64 for (i = 0; i < length; ++i) {
65 herr_t status = threadsafe_H5Tenum_insert(dtype_id, names[i], values + i);
66 if (status < 0) {
67 threadsafe_H5Tclose(dtype_id);
69 }
70 }
71 return dtype_id;
72}
73
74/* creates HDF5 float complex data type; use H5Tclose() to free */
75typedef struct { float re; float im; } internal_float_complex_type;
76static hid_t XLALH5TypeNativeFloatComplex(void)
77{
78 hid_t dtype_id;
79 dtype_id = threadsafe_H5Tcreate(H5T_COMPOUND, sizeof(internal_float_complex_type));
80 threadsafe_H5Tinsert(dtype_id, "r", HOFFSET(internal_float_complex_type, re), H5T_NATIVE_FLOAT);
81 threadsafe_H5Tinsert(dtype_id, "i", HOFFSET(internal_float_complex_type, im), H5T_NATIVE_FLOAT);
82 return dtype_id;
83}
84
85/* creates HDF5 double complex data type; use H5Tclose() to free */
86typedef struct { double re; double im; } internal_double_complex_type;
87static hid_t XLALH5TypeNativeDoubleComplex(void)
88{
89 hid_t dtype_id;
90 dtype_id = threadsafe_H5Tcreate(H5T_COMPOUND, sizeof(internal_double_complex_type));
91 threadsafe_H5Tinsert(dtype_id, "r", HOFFSET(internal_double_complex_type, re), H5T_NATIVE_DOUBLE);
92 threadsafe_H5Tinsert(dtype_id, "i", HOFFSET(internal_double_complex_type, im), H5T_NATIVE_DOUBLE);
93 return dtype_id;
94}
95
96/* creates HDF5 LIGOTimeGPS type; use H5Tclose() to free */
97static hid_t XLALH5TypeNativeLIGOTimeGPS(void)
98{
99 hid_t dtype_id;
100 hid_t int32_dtype_id;
101 int32_dtype_id = threadsafe_H5Tcopy(H5T_NATIVE_INT);
102 threadsafe_H5Tset_size(int32_dtype_id, 4); // 4 bytes = 32 bits
103 dtype_id = threadsafe_H5Tcreate(H5T_COMPOUND, sizeof(LIGOTimeGPS));
104 threadsafe_H5Tinsert(dtype_id, "gpsSeconds", HOFFSET(LIGOTimeGPS, gpsSeconds), int32_dtype_id);
105 threadsafe_H5Tinsert(dtype_id, "gpsNanoSeconds", HOFFSET(LIGOTimeGPS, gpsNanoSeconds), int32_dtype_id);
106 threadsafe_H5Tclose(int32_dtype_id);
107 return dtype_id;
108}
109
110/* converts LALTYPECODE to HDF5 type; use H5Tclose() to free */
111static hid_t XLALH5TypeFromLALType(LALTYPECODE dtype)
112{
113 hid_t dtype_id;
114 size_t size = 1U << (dtype & LAL_TYPE_SIZE_MASK);
115
116 /* allow only supported data types */
117 switch (dtype) {
119 case LAL_I2_TYPE_CODE:
120 case LAL_I4_TYPE_CODE:
121 case LAL_I8_TYPE_CODE:
123 case LAL_U2_TYPE_CODE:
124 case LAL_U4_TYPE_CODE:
125 case LAL_U8_TYPE_CODE:
126 case LAL_S_TYPE_CODE:
127 case LAL_D_TYPE_CODE:
128 case LAL_C_TYPE_CODE:
129 case LAL_Z_TYPE_CODE:
130 /* these are all supported */
131 break;
132 default:
133 /* anything else is not */
134 XLAL_ERROR(XLAL_ETYPE, "Unsupported LALTYPECODE value 0%o", (unsigned int)dtype);
135 }
136
137 if ((dtype & LAL_CMPLX_TYPE_FLAG)) {
138 /* complex numbers are treated as compound types */
139 switch (size) {
140 case 8:
141 dtype_id = XLALH5TypeNativeFloatComplex();
142 break;
143 case 16:
144 dtype_id = XLALH5TypeNativeDoubleComplex();
145 break;
146 default:
147 /* it should be impossible to get here */
148 XLAL_ERROR(XLAL_ETYPE, "Not reached");
149 }
150 } else if ((dtype & LAL_FLTPT_TYPE_FLAG)) {
151 /* floating point number */
152 switch (size) {
153 case 4:
154 dtype_id = threadsafe_H5Tcopy(H5T_NATIVE_FLOAT);
155 break;
156 case 8:
157 dtype_id = threadsafe_H5Tcopy(H5T_NATIVE_DOUBLE);
158 break;
159 default:
160 /* it should be impossible to get here */
161 XLAL_ERROR(XLAL_ETYPE, "Not reached");
162 }
163 } else if ((dtype & LAL_UNSGN_TYPE_FLAG)) {
164 /* unsigned integer */
165 switch (size) {
166 case 1:
167 dtype_id = threadsafe_H5Tcopy(H5T_NATIVE_UCHAR);
168 break;
169 case 2:
170 dtype_id = threadsafe_H5Tcopy(H5T_NATIVE_UINT16);
171 break;
172 case 4:
173 dtype_id = threadsafe_H5Tcopy(H5T_NATIVE_UINT32);
174 break;
175 case 8:
176 dtype_id = threadsafe_H5Tcopy(H5T_NATIVE_UINT64);
177 break;
178 default:
179 /* it should be impossible to get here */
180 XLAL_ERROR(XLAL_ETYPE, "Not reached");
181 }
182 } else {
183 switch (size) {
184 case 1:
185 dtype_id = threadsafe_H5Tcopy(H5T_NATIVE_SCHAR);
186 break;
187 case 2:
188 dtype_id = threadsafe_H5Tcopy(H5T_NATIVE_INT16);
189 break;
190 case 4:
191 dtype_id = threadsafe_H5Tcopy(H5T_NATIVE_INT32);
192 break;
193 case 8:
194 dtype_id = threadsafe_H5Tcopy(H5T_NATIVE_INT64);
195 break;
196 default:
197 /* it should be impossible to get here */
198 XLAL_ERROR(XLAL_ETYPE, "Not reached");
199 }
200 }
201
202 return dtype_id;
203}
204
205/* converts HDF5 type to LALTYPECODE */
206static LALTYPECODE XLALTypeFromH5Type(hid_t dtype_id)
207{
208 LALTYPECODE dtype = 0;
209 switch (threadsafe_H5Tget_class(dtype_id)) {
210 case H5T_INTEGER:
211 switch (threadsafe_H5Tget_sign(dtype_id)) {
212 case H5T_SGN_NONE:
213 dtype |= LAL_UNSGN_TYPE_FLAG;
214 break;
215 default:
216 /* do nothing */
217 break;
218 }
219 switch (threadsafe_H5Tget_size(dtype_id)) {
220 case 1:
221 dtype |= LAL_1_BYTE_TYPE_SIZE;
222 break;
223 case 2:
224 dtype |= LAL_2_BYTE_TYPE_SIZE;
225 break;
226 case 4:
227 dtype |= LAL_4_BYTE_TYPE_SIZE;
228 break;
229 case 8:
230 dtype |= LAL_8_BYTE_TYPE_SIZE;
231 break;
232 default:
233 XLAL_ERROR(XLAL_ETYPE, "Unsupported data type\n");
234 break;
235 }
236 break;
237 case H5T_FLOAT:
238 dtype |= LAL_FLTPT_TYPE_FLAG;
239 switch (threadsafe_H5Tget_size(dtype_id)) {
240 case 4:
241 dtype |= LAL_4_BYTE_TYPE_SIZE;
242 break;
243 case 8:
244 dtype |= LAL_8_BYTE_TYPE_SIZE;
245 break;
246 default:
247 XLAL_ERROR(XLAL_ETYPE, "Unsupported data type\n");
248 break;
249 }
250 break;
251 case H5T_COMPOUND: {
252 /* note: complex numbers are the only compound type supported */
253 char *s;
254
255 /* sanity check the dtype_id */
256
257 /* must have 2 members ... */
258 if (threadsafe_H5Tget_nmembers(dtype_id) != 2)
259 XLAL_ERROR(XLAL_ETYPE, "Unsupported data type\n");
260
261 /* both members must be floating-point type ... */
262 if (threadsafe_H5Tget_member_class(dtype_id, 0) != H5T_FLOAT)
263 XLAL_ERROR(XLAL_ETYPE, "Unsupported data type\n");
264 if (threadsafe_H5Tget_member_class(dtype_id, 1) != H5T_FLOAT)
265 XLAL_ERROR(XLAL_ETYPE, "Unsupported data type\n");
266
267 /* first member name must be something like "real" ... */
268 s = threadsafe_H5Tget_member_name(dtype_id, 0);
269 if (XLALStringNCaseCompare(s, "real", strlen(s)) != 0) {
270 free(s);
271 XLAL_ERROR(XLAL_ETYPE, "Unsupported data type\n");
272 }
273 free(s);
274
275 /* second member name must be something like "imaginary" ... */
276 s = threadsafe_H5Tget_member_name(dtype_id, 1);
277 if (XLALStringNCaseCompare(s, "imaginary", strlen(s)) != 0) {
278 free(s);
279 XLAL_ERROR(XLAL_ETYPE, "Unsupported data type\n");
280 }
281 free(s);
282
284 switch (threadsafe_H5Tget_size(dtype_id)) {
285 case 8:
286 dtype |= LAL_8_BYTE_TYPE_SIZE;
287 break;
288 case 16:
289 dtype |= LAL_16_BYTE_TYPE_SIZE;
290 break;
291 default:
292 XLAL_ERROR(XLAL_ETYPE, "Unsupported data type\n");
293 break;
294 }
295 break;
296 }
297 case H5T_STRING:
298 /* overload CHAR type */
299 return LAL_CHAR_TYPE_CODE;
300 default:
301 XLAL_ERROR(XLAL_ETYPE, "Unsupported data type\n");
302 break;
303 }
304 return dtype;
305}
306
307/* creates a HDF5 file for writing */
308static LALH5File * XLALH5FileCreate(const char *path)
309{
310 char tmpfname[FILENAME_MAX];
312 if (snprintf(tmpfname, sizeof(tmpfname), "%s.tmp", path) < 0)
314 file = LALCalloc(1, sizeof(*file));
315 if (!file)
317 XLALStringCopy(file->fname, path, sizeof(file->fname));
318 file->file_id = threadsafe_H5Fcreate(tmpfname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
319 if (file->file_id < 0) {
320 LALFree(file);
321 XLAL_ERROR_NULL(XLAL_EIO, "Could not create HDF5 file `%s'", path);
322 }
323 file->mode = LAL_H5_FILE_MODE_WRITE;
324 return file;
325}
326
327/* opens a HDF5 file for reading */
328static LALH5File * XLALH5FileOpenRead(const char *path)
329{
331 file = LALCalloc(1, sizeof(*file));
332 if (!file)
334 file->file_id = threadsafe_H5Fopen(path, H5F_ACC_RDONLY, H5P_DEFAULT);
335 if (file->file_id < 0) {
336 LALFree(file);
337 XLAL_ERROR_NULL(XLAL_EIO, "Could not open HDF5 file `%s'", path);
338 }
339 file->mode = LAL_H5_FILE_MODE_READ;
340 return file;
341}
342
343#if 0
344static hid_t XLALGetObjectIdentifier(const void *ptr)
345{
346 /*
347 * use type punning to get the identifier
348 * note that the identifier is always the
349 * first member of the LALH5 types
350 */
351 union { const void *ptr; const hid_t *hid; } id = {ptr};
352 if (ptr == NULL)
354 return *id.hid;
355}
356#endif
357
358#endif /* HAVE_HDF5 */
359
360/* EXPORTED ROUTINES */
361
362/**
363 * @addtogroup H5FileIOLowLevel_c
364 * @brief Low-level routines for reading/writing HDF5 files.
365 * @details
366 * These routines are basic routines for accessing HDF5 files.
367 * The mid-level and high-level routines, which are based on
368 * these routines, are typically more convenient routines to use.
369 * @{
370 */
371
372/**
373 * @name File/Group Routines
374 * @{
375 */
376
377/**
378 * @brief Closes a ::LALH5File
379 * @details
380 * This routine closes a ::LALH5File and deallocates resources
381 * associated with it. If the file was opened for writing, this
382 * routine also renames the temporary file as the actual file.
383 *
384 * @param file A pointer to a ::LALH5File structure to close.
385 */
387{
388#ifndef HAVE_HDF5
389 XLAL_ERROR_VOID(XLAL_EFAILED, "HDF5 support not implemented");
390#else
391 if (file) {
392 if (file->is_a_group)
393 threadsafe_H5Gclose(file->file_id);
394 else {
395 if (file->mode == LAL_H5_FILE_MODE_WRITE) {
396 char tmpfname[FILENAME_MAX];
397 size_t namelen;
398 namelen = threadsafe_H5Fget_name(file->file_id, NULL, 0);
399 if (sizeof(tmpfname) <= namelen) {
400 threadsafe_H5Fclose(file->file_id);
401 LALFree(file);
402 XLAL_ERROR_VOID(XLAL_EIO, "Failed to move temporary file");
403 }
404 threadsafe_H5Fget_name(file->file_id, tmpfname, sizeof(tmpfname));
405 threadsafe_H5Fflush(file->file_id , H5F_SCOPE_GLOBAL);
406 if (rename(tmpfname, file->fname) < 0) {
407 threadsafe_H5Fclose(file->file_id);
408 LALFree(file);
409 XLAL_ERROR_VOID(XLAL_EIO, "Failed to move temporary file");
410 }
411 }
412 threadsafe_H5Fclose(file->file_id);
413 }
414 LALFree(file);
415 }
416 return;
417#endif
418}
419
420/**
421 * @brief Opens a ::LALH5File
422 * @details
423 * Opens a HDF5 file with pathname @p path and creates a ::LALH5File structure
424 * associated with it.
425 *
426 * The @p mode parameter points to a string that determines whether the
427 * file is being opened for reading and writing. Allowed strings are:
428 *
429 * <dl>
430 * <dt>r</dt><dd>Open file for reading.</dd>
431 * <dt>w</dt><dd>Truncate to zero length or create file for writing.</dd>
432 * </dl>
433 *
434 * If a file is opened for writing then data is initially written to a
435 * temporary file, and this file is renamed once the ::LALH5File structure
436 * is closed with XLALH5FileClose().
437 *
438 * @param path Pointer to a string containing the path of the file to open.
439 * @param mode Mode to open the file, either "r" or "w".
440 * @returns A pointer to a ::LALH5File structure associated with the
441 * specified HDF5 file.
442 * @retval NULL An error occurred opening the file.
443 */
444LALH5File * XLALH5FileOpen(const char UNUSED *path, const char UNUSED *mode)
445{
446#ifndef HAVE_HDF5
447 XLAL_ERROR_NULL(XLAL_EFAILED, "HDF5 support not implemented");
448#else
449 if (path == NULL || mode == NULL)
451 if (strcmp(mode, "r") == 0)
452 return XLALH5FileOpenRead(path);
453 else if (strcmp(mode, "w") == 0)
454 return XLALH5FileCreate(path);
455 XLAL_ERROR_NULL(XLAL_EINVAL, "Invalid mode \"%s\": must be either \"r\" or \"w\"", mode);
456#endif
457}
458
459/**
460 * @brief Opens a group in a ::LALH5File
461 * @details
462 * Opens a HDF5 group with name @p name contained in the HDF5 file
463 * associated with the ::LALH5File @p file. If the HDF5 file is
464 * being read, the specified group must exist in that file. If
465 * the HDF5 file is being written, the specified group is created
466 * within the file.
467 *
468 * @param file Pointer to a ::LALH5File structure in which to open the group.
469 * @param name Pointer to a string with the name of the group to open.
470 * @returns A pointer to a ::LALH5File structure associated with the
471 * specified group within a HDF5 file.
472 * @retval NULL An error occurred opening the group.
473 */
474LALH5File * XLALH5GroupOpen(LALH5File UNUSED *file, const char UNUSED *name)
475{
476#ifndef HAVE_HDF5
477 XLAL_ERROR_NULL(XLAL_EFAILED, "HDF5 support not implemented");
478#else
479 LALH5File *group;
480 if (file == NULL)
482 group = LALCalloc(1, sizeof(*group));
483 if (!group)
485 group->is_a_group = 1;
486 group->mode = file->mode;
487 if (!name) /* this is the same as the file */
488 group->file_id = file->file_id;
489 else if (group->mode == LAL_H5_FILE_MODE_READ)
490 group->file_id = threadsafe_H5Gopen2(file->file_id, name, H5P_DEFAULT);
491 else if (group->mode == LAL_H5_FILE_MODE_WRITE) {
492 hid_t gcpl; /* property list to allow intermediate groups to be created */
493 gcpl = threadsafe_H5Pcreate(H5P_LINK_CREATE);
494 if (gcpl < 0 || threadsafe_H5Pset_create_intermediate_group(gcpl, 1) < 0) {
495 LALFree(group);
497 }
498 group->file_id = threadsafe_H5Gcreate2(file->file_id, name, gcpl, H5P_DEFAULT, H5P_DEFAULT);
499 threadsafe_H5Pclose(gcpl);
500 } else
501 XLAL_ERROR_NULL(XLAL_EINVAL, "Corrupted file structure");
502 if (group->file_id < 0) {
503 LALFree(group);
504 XLAL_ERROR_NULL(XLAL_EIO, "Failed to open group `%s'", name ? name : "(null)");
505 }
506 return group;
507#endif
508}
509
510/**
511 * @brief Checks for existence of a group in a ::LALH5File
512 * @details
513 * Checks if group with name @p name exists in the HDF5 file associated with the
514 * ::LALH5File file @p file. If the group exists the return code is 1.
515 * If the group does not exist a return code value of 0 is used.
516 *
517 * @attention Read failure results in a returned value of 0.
518 *
519 * @param file Pointer to a ::LALH5File structure to check for group.
520 * @param name Pointer to a string with the name of the group to check.
521 * @retval 0 Group does not exist or failure.
522 * @retval 1 Group exists.
523 */
524int XLALH5FileCheckGroupExists(const LALH5File UNUSED *file, const char UNUSED *name)
525{
526#ifndef HAVE_HDF5
527 XLAL_ERROR_VAL(0, XLAL_EFAILED, "HDF5 support not implemented");
528#else
529 if (file == NULL || name == NULL)
531 H5G_info_t info;
532 if (threadsafe_H5Gget_info_by_name(file->file_id, name, &info, H5P_DEFAULT) < 0)
533 return 0;
534 return 1;
535#endif
536}
537
538/**
539 * @brief Checks for existence of a dataset in a ::LALH5File
540 * @details
541 * Checks if dataset with name @p name exists in the HDF5 file associated with the
542 * ::LALH5File file @p file. If the dataset exists the return code is 1.
543 * If the dataset does not exist a return code value of 0 is used.
544 *
545 * @attention Read failure results in a returned value of 0.
546 *
547 * @param file Pointer to a ::LALH5File structure to check for dataset.
548 * @param name Pointer to a string with the name of the dataset to check.
549 * @retval 0 Dataset does not exist or failure.
550 * @retval 1 Dataset exists.
551 */
552int XLALH5FileCheckDatasetExists(const LALH5File UNUSED *file, const char UNUSED *name)
553{
554#ifndef HAVE_HDF5
555 XLAL_ERROR_VAL(0, XLAL_EFAILED, "HDF5 support not implemented");
556#else
557 H5G_info_t group_info;
558 hsize_t i;
559
560 if (file == NULL || name == NULL)
562
563 if (threadsafe_H5Gget_info(file->file_id, &group_info) < 0)
564 XLAL_ERROR_VAL(0, XLAL_EIO, "Could not read group info");
565
566 for (i = 0; i < group_info.nlinks; ++i) {
567 H5O_info_t obj_info;
568 if (threadsafe_H5Oget_info_by_idx(file->file_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &obj_info, H5P_DEFAULT) < 0)
569 XLAL_ERROR_VAL(0, XLAL_EIO, "Could not read object info");
570 if (obj_info.type == H5O_TYPE_DATASET) {
571 char *base;
572 hid_t obj_id;
573 int n;
574 obj_id = threadsafe_H5Oopen_by_addr(file->file_id, obj_info.addr);
575 if (obj_id < 0)
576 XLAL_ERROR_VAL(0, XLAL_EIO, "Could not open object");
577 n = threadsafe_H5Iget_name(obj_id, NULL, 0);
578 if (n < 0) {
579 threadsafe_H5Oclose(obj_id);
580 XLAL_ERROR_VAL(0, XLAL_EIO, "Could not read object");
581 }
582 char dset_name[n + 1];
583 n = threadsafe_H5Iget_name(obj_id, dset_name, n + 1);
584 threadsafe_H5Oclose(obj_id);
585 if (n < 0)
586 XLAL_ERROR_VAL(0, XLAL_EIO, "Could not read object");
587 /* get basename */
588 if ((base = strrchr(dset_name, '/')))
589 ++base;
590 else
591 base = dset_name;
592
593 if (strcmp(name, base) == 0)
594 return 1; /* found it */
595 }
596 }
597
598 /* no matching dataset found */
599 return 0;
600#endif
601}
602
603/**
604 * @brief DEPRECATED: Checks for existence of a Group in a LALH5File object ::LALH5File
605 * @details
606 * Checks if group with name @p exists in the HDF5 files associated with the
607 * ::LALH5File file. If the group exists the return code is 1
608 * if the group does not exist a return code value of 0 is used.
609 *
610 * @deprecated
611 * Use XLALH5FileCheckGroupExists instead.
612 *
613 * @param file Pointer to a ::LALH5File structure to check for group in
614 * @param name Pointer to a string with the name of the group to check.
615 * @returns int, 1 if group exists. 0 if not.
616 */
617int XLALH5CheckGroupExists(LALH5File UNUSED *file, const char UNUSED *name)
618{
619#ifndef HAVE_HDF5
620 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
621#else
622 XLAL_PRINT_DEPRECATION_WARNING("XLALH5FileCheckGroupExists");
623 if (threadsafe_H5Gget_objinfo(file->file_id, name, 0, NULL))
624 {
625 return 0;
626 }
627 else
628 {
629 return 1;
630 }
631#endif
632}
633
634/**
635 * @brief Gets the number of groups contained in a ::LALH5File
636 * @details
637 * This routines returns the number of groups contained in a
638 * an ::LALH5File @p file which can be either a file or a group.
639 * This routine does not recursively count subgroups of the
640 * groups found.
641 *
642 * @param file Pointer to a ::LALH5File file or group to be queried.
643 * @returns The number of groups contained in the file or group.
644 * @retval -1 Failure.
645 */
647{
648#ifndef HAVE_HDF5
649 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
650#else
651 H5G_info_t group_info;
652 size_t num = 0;
653 hsize_t i;
654
655 if (file == NULL)
657
658 if (threadsafe_H5Gget_info(file->file_id, &group_info) < 0)
659 XLAL_ERROR(XLAL_EIO, "Could not read group info");
660
661 for (i = 0; i < group_info.nlinks; ++i) {
662 H5O_info_t obj_info;
663 if (threadsafe_H5Oget_info_by_idx(file->file_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &obj_info, H5P_DEFAULT) < 0)
664 XLAL_ERROR(XLAL_EIO, "Could not read object info");
665 if (obj_info.type == H5O_TYPE_GROUP)
666 ++num;
667 }
668
669 return num;
670#endif
671}
672
673/**
674 * @brief Gets the name of a group contained in a ::LALH5File
675 * @details
676 * This routines gets the name of a group contained in a ::LALH5File
677 * @p file which can be either a file or a group.
678 * The index @p pos identifies which group's name is returned.
679 * The result is written into the buffer pointed to by @p name, the size
680 * of which is @p size bytes. If @p name is NULL, no data is copied but
681 * the routine returns the length of the string. Therefore, this routine
682 * can be called once to determine the amount of memory required, the
683 * memory can be allocated, and then it can be called a second time to
684 * read the string. If the parameter @p size is less than or equal to
685 * the string length then only $p size-1 bytes of the string are copied
686 * to the buffer @p name.
687 * @note The return value is the length of the string, not including the
688 * terminating NUL character; thus the buffer @p name should be allocated
689 * to be one byte larger.
690 * @param name Pointer to a buffer into which the string will be written.
691 * @param size Size in bytes of the buffer into which the string will be
692 * written.
693 * @param file Pointer to a ::LALH5File file or group to be queried.
694 * @param pos The index identifying which group contained in the file.
695 * @retval 0 Success.
696 * @retval -1 Failure.
697 */
698int XLALH5FileQueryGroupName(char UNUSED *name, size_t UNUSED size, const LALH5File UNUSED *file, int UNUSED pos)
699{
700#ifndef HAVE_HDF5
701 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
702#else
703 H5G_info_t group_info;
704 size_t num = 0;
705 hsize_t i;
706
707 if (file == NULL)
709
710 if (threadsafe_H5Gget_info(file->file_id, &group_info) < 0)
711 XLAL_ERROR(XLAL_EIO, "Could not read group info");
712
713 for (i = 0; i < group_info.nlinks; ++i) {
714 H5O_info_t obj_info;
715 if (threadsafe_H5Oget_info_by_idx(file->file_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &obj_info, H5P_DEFAULT) < 0)
716 XLAL_ERROR(XLAL_EIO, "Could not read object info");
717 if (obj_info.type == H5O_TYPE_GROUP) {
718 if (num == (size_t)pos) { /* found it */
719 hid_t obj_id;
720 int n;
721 obj_id = threadsafe_H5Oopen_by_addr(file->file_id, obj_info.addr);
722 if (obj_id < 0)
723 XLAL_ERROR(XLAL_EIO, "Could not open object");
724 n = threadsafe_H5Iget_name(obj_id, name, size);
725 threadsafe_H5Oclose(obj_id);
726 if (n < 0)
727 XLAL_ERROR(XLAL_EIO, "Could not read object name");
728 return n;
729 } else
730 ++num;
731 }
732 }
733
734 /* failed to find position */
735 XLAL_ERROR(XLAL_EINVAL, "No group associated with given position");
736#endif
737}
738
739/**
740 * @brief Gets the number of datasets contained in a ::LALH5File
741 * @details
742 * This routines returns the number of datasets contained in a
743 * an ::LALH5File @p file which can be either a file or a group.
744 *
745 * @param file Pointer to a ::LALH5File file or group to be queried.
746 * @returns The number of datasets contained in the file or group.
747 * @retval -1 Failure.
748 */
750{
751#ifndef HAVE_HDF5
752 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
753#else
754 H5G_info_t group_info;
755 size_t num = 0;
756 hsize_t i;
757
758 if (file == NULL)
760
761 if (threadsafe_H5Gget_info(file->file_id, &group_info) < 0)
762 XLAL_ERROR(XLAL_EIO, "Could not read group info");
763
764 for (i = 0; i < group_info.nlinks; ++i) {
765 H5O_info_t obj_info;
766 if (threadsafe_H5Oget_info_by_idx(file->file_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &obj_info, H5P_DEFAULT) < 0)
767 XLAL_ERROR(XLAL_EIO, "Could not read object info");
768 if (obj_info.type == H5O_TYPE_DATASET)
769 ++num;
770 }
771
772 return num;
773#endif
774}
775
776/**
777 * @brief Gets the name of a dataset contained in a ::LALH5File
778 * @details
779 * This routines gets the name of a dataset contained in a ::LALH5File
780 * @p file which can be either a file or a group.
781 * The index @p pos identifies which dataset's name is returned.
782 * The result is written into the buffer pointed to by @p name, the size
783 * of which is @p size bytes. If @p name is NULL, no data is copied but
784 * the routine returns the length of the string. Therefore, this routine
785 * can be called once to determine the amount of memory required, the
786 * memory can be allocated, and then it can be called a second time to
787 * read the string. If the parameter @p size is less than or equal to
788 * the string length then only $p size-1 bytes of the string are copied
789 * to the buffer @p name.
790 * @note The return value is the length of the string, not including the
791 * terminating NUL character; thus the buffer @p name should be allocated
792 * to be one byte larger.
793 * @param name Pointer to a buffer into which the string will be written.
794 * @param size Size in bytes of the buffer into which the string will be
795 * written.
796 * @param file Pointer to a ::LALH5File file or group to be queried.
797 * @param pos The index identifying which dataset contained in the file.
798 * @retval 0 Success.
799 * @retval -1 Failure.
800 */
801int XLALH5FileQueryDatasetName(char UNUSED *name, size_t UNUSED size, const LALH5File UNUSED *file, int UNUSED pos)
802{
803#ifndef HAVE_HDF5
804 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
805#else
806 H5G_info_t group_info;
807 size_t num = 0;
808 hsize_t i;
809
810 if (file == NULL)
812
813 if (threadsafe_H5Gget_info(file->file_id, &group_info) < 0)
814 XLAL_ERROR(XLAL_EIO, "Could not read group info");
815
816 for (i = 0; i < group_info.nlinks; ++i) {
817 H5O_info_t obj_info;
818 if (threadsafe_H5Oget_info_by_idx(file->file_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &obj_info, H5P_DEFAULT) < 0)
819 XLAL_ERROR(XLAL_EIO, "Could not read object info");
820 if (obj_info.type == H5O_TYPE_DATASET) {
821 if (num == (size_t)pos) { /* found it */
822 hid_t obj_id;
823 int n;
824 obj_id = threadsafe_H5Oopen_by_addr(file->file_id, obj_info.addr);
825 if (obj_id < 0)
826 XLAL_ERROR(XLAL_EIO, "Could not open object");
827 n = threadsafe_H5Iget_name(obj_id, name, size);
828 threadsafe_H5Oclose(obj_id);
829 if (n < 0)
830 XLAL_ERROR(XLAL_EIO, "Could not read object name");
831 return n;
832 } else
833 ++num;
834 }
835 }
836
837 /* failed to find position */
838 XLAL_ERROR(XLAL_EINVAL, "No dataset associated with given position");
839#endif
840}
841
842/**
843 * @brief DEPRECATED: Gets dataset names from a ::LALH5File
844 * @details
845 * This routine returns the names of all datasets in a ::LALH5File.
846 *
847 * @deprecated
848 * Use XLALH5AttributeQueryN() and XLALH5AttributeQueryName() instead.
849 *
850 * @param names Pointer a list of strings to be returned to the user. Memory
851 * should be freed by the caller.
852 * @param N Pointer to a UINT4 where the number of datasets will be recorded
853 * @param file ::LALH5File from which to read datasets
854 * @retval 0 Success.
855 * @retval -1 Failure.
856 */
857int XLALH5FileGetDatasetNames(LALH5File UNUSED *file, char UNUSED *** names, UINT4 UNUSED *N)
858{
859#ifndef HAVE_HDF5
860 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
861#else
862 hsize_t ng;
863 int ns;
864 int otype;
865 int i;
866
867 XLAL_PRINT_DEPRECATION_WARNING("XLALH5FileQueryNDatasets() and XLALH5FileQueryDatasetName");
868
869 if (file == NULL)
871 if (names == NULL)
873
874 threadsafe_H5Gget_num_objs(file->file_id, &ng);
875 *N = ng;
876
877 /*
878 * Filter objects that don't meet our requirements
879 */
880 for (i = 0; i < (int)ng; i++) {
881 otype = threadsafe_H5Gget_objtype_by_idx(file->file_id, (size_t)i);
882 if (otype != H5G_DATASET) {
883 (*N)--;
884 }
885 }
886 char ** namelist = (char**) XLALMalloc((*N) * sizeof(*names));
887
888 for (i = 0; i < (int)ng; i++) {
889 otype = threadsafe_H5Gget_objtype_by_idx(file->file_id, (size_t)i);
890 if (otype != H5G_DATASET) {
891 continue;
892 }
893
894 ns = threadsafe_H5Gget_objname_by_idx(file->file_id, (size_t)i, NULL, 0) + 1;
895 namelist[i] = (char*) XLALMalloc(ns * sizeof(namelist[i]));
896 threadsafe_H5Gget_objname_by_idx(file->file_id, (size_t)i, namelist[i], ns);
897 }
898
899 *names = namelist;
900 return(XLAL_SUCCESS);
901#endif
902}
903
904/** @} */
905
906/**
907 * @name Dataset Routines
908 * @{
909 */
910
911/**
912 * @brief Frees a ::LALH5Dataset
913 * @details
914 * Closes a HDF5 dataset associated with the ::LALH5Dataset @p dset
915 * and deallocates memory of the ::LALH5Dataset structure.
916 * @param dset Pointer to a ::LALH5Dataset structure to close.
917 */
919{
920#ifndef HAVE_HDF5
921 XLAL_ERROR_VOID(XLAL_EFAILED, "HDF5 support not implemented");
922#else
923 if (dset) {
924 threadsafe_H5Tclose(dset->dtype_id);
925 threadsafe_H5Sclose(dset->space_id);
926 threadsafe_H5Dclose(dset->dataset_id);
927 LALFree(dset);
928 }
929 return;
930#endif
931}
932
933/**
934 * @brief Allocates a multi-dimensional ::LALH5Dataset
935 * @details
936 * Creates a new HDF5 dataset with name @p name within a HDF5 file
937 * associated with the ::LALH5File @p file structure and allocates a
938 * ::LALH5Dataset structure associated with the dataset. The type
939 * of data to be stored in the dataset is given by the \c LALTYPECODE
940 * @p dtype and the rank array dimensions of the dataset is given by
941 * the UINT4Vector @p dimLength.
942 *
943 * The ::LALH5File @p file passed to this routine must be a file
944 * opened for writing.
945 *
946 * @param file Pointer to a ::LALH5File structure in which to create the dataset.
947 * @param name Pointer to a string with the name of the dataset to create.
948 * @param dtype \c LALTYPECODE value specifying the data type.
949 * @param dimLength Pointer to a UINT4Vector specifying the dataspace
950 * dimensions.
951 * @returns A pointer to a ::LALH5Dataset structure associated with the
952 * specified dataset within a HDF5 file.
953 * @retval NULL An error occurred creating the dataset.
954 */
955LALH5Dataset * XLALH5DatasetAlloc(LALH5File UNUSED *file, const char UNUSED *name, LALTYPECODE UNUSED dtype, UINT4Vector UNUSED *dimLength)
956{
957#ifndef HAVE_HDF5
958 XLAL_ERROR_NULL(XLAL_EFAILED, "HDF5 support not implemented");
959#else
960 LALH5Dataset *dset;
961 hsize_t *dims;
962 UINT4 dim;
963 size_t namelen;
964
965 if (name == NULL || file == NULL || dimLength == NULL)
967 if (file->mode != LAL_H5_FILE_MODE_WRITE)
968 XLAL_ERROR_NULL(XLAL_EINVAL, "Attempting to write to a read-only HDF5 file");
969
970 namelen = strlen(name);
971 dset = LALCalloc(1, sizeof(*dset) + namelen + 1); /* use flexible array member to record name */
972 if (!dset)
974
975 /* create datatype */
976 dset->dtype_id = XLALH5TypeFromLALType(dtype);
977 if (dset->dtype_id < 0) {
978 LALFree(dset);
980 }
981
982 /* copy dimensions to HDF5 type */
983 dims = LALCalloc(dimLength->length, sizeof(*dims));
984 if (!dims) {
985 threadsafe_H5Tclose(dset->dtype_id);
986 LALFree(dset);
988 }
989 for (dim = 0; dim < dimLength->length; ++dim)
990 dims[dim] = dimLength->data[dim];
991
992 /* create dataspace */
993 dset->space_id = threadsafe_H5Screate_simple(dimLength->length, dims, NULL);
994 LALFree(dims);
995 if (dset->space_id < 0) {
996 threadsafe_H5Tclose(dset->dtype_id);
997 LALFree(dset);
998 XLAL_ERROR_NULL(XLAL_EIO, "Could not create dataspace for dataset `%s'", name);
999 }
1000
1001 /* create dataset */
1002 dset->dataset_id = threadsafe_H5Dcreate2(file->file_id, name, dset->dtype_id, dset->space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1003 if (dset->dataset_id < 0) {
1004 threadsafe_H5Tclose(dset->dtype_id);
1005 threadsafe_H5Sclose(dset->space_id);
1006 LALFree(dset);
1007 XLAL_ERROR_NULL(XLAL_EIO, "Could not create dataset `%s'", name);
1008 }
1009
1010 /* record name of dataset and parent id */
1011 snprintf(dset->name, namelen + 1, "%s", name);
1012 dset->parent_id = file->file_id;
1013
1014 return dset;
1015#endif
1016}
1017
1018/**
1019 * @brief Allocates a 1-dimensional ::LALH5Dataset
1020 * @details
1021 * Creates a new HDF5 dataset with name @p name within a HDF5 file
1022 * associated with the ::LALH5File @p file structure and allocates a
1023 * ::LALH5Dataset structure associated with the dataset. The type
1024 * of data to be stored in the dataset is given by the \c LALTYPECODE
1025 * @p dtype and the number of points in the dataset is given by
1026 * the @p length parameter.
1027 *
1028 * The ::LALH5File @p file passed to this routine must be a file
1029 * opened for writing.
1030 *
1031 * @param file Pointer to a ::LALH5File structure in which to create the dataset.
1032 * @param name Pointer to a string with the name of the dataset to create.
1033 * @param dtype \c LALTYPECODE value specifying the data type.
1034 * @param length The number of points of data in the dataset.
1035 * @returns A pointer to a ::LALH5Dataset structure associated with the
1036 * specified dataset within a HDF5 file.
1037 * @retval NULL An error occurred creating the dataset.
1038 */
1039LALH5Dataset * XLALH5DatasetAlloc1D(LALH5File UNUSED *file, const char UNUSED *name, LALTYPECODE UNUSED dtype, size_t UNUSED length)
1040{
1041#ifndef HAVE_HDF5
1042 XLAL_ERROR_NULL(XLAL_EFAILED, "HDF5 support not implemented");
1043#else
1044 LALH5Dataset *dset;
1045 hsize_t npoints = length;
1046 size_t namelen;
1047
1048 if (name == NULL || file == NULL)
1050 if (file->mode != LAL_H5_FILE_MODE_WRITE)
1051 XLAL_ERROR_NULL(XLAL_EINVAL, "Attempting to write to a read-only HDF5 file");
1052
1053 namelen = strlen(name);
1054 dset = LALCalloc(1, sizeof(*dset) + namelen + 1); /* use flexible array member to record name */
1055 if (!dset)
1057
1058 /* create datatype */
1059 dset->dtype_id = XLALH5TypeFromLALType(dtype);
1060 if (dset->dtype_id < 0) {
1061 LALFree(dset);
1063 }
1064
1065 /* create dataspace */
1066 dset->space_id = threadsafe_H5Screate_simple(1, &npoints, NULL);
1067 if (dset->space_id < 0) {
1068 threadsafe_H5Tclose(dset->dtype_id);
1069 LALFree(dset);
1070 XLAL_ERROR_NULL(XLAL_EIO, "Could not create dataspace for dataset `%s'", name);
1071 }
1072
1073 /* create dataset */
1074 dset->dataset_id = threadsafe_H5Dcreate2(file->file_id, name, dset->dtype_id, dset->space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1075 if (dset->dataset_id < 0) {
1076 threadsafe_H5Tclose(dset->dtype_id);
1077 threadsafe_H5Sclose(dset->space_id);
1078 LALFree(dset);
1079 XLAL_ERROR_NULL(XLAL_EIO, "Could not create dataset `%s'", name);
1080 }
1081
1082 /* record name of dataset and parent id */
1083 snprintf(dset->name, namelen + 1, "%s", name);
1084 dset->parent_id = file->file_id;
1085
1086 return dset;
1087#endif
1088}
1089
1090/**
1091 * @brief Allocates a variable-length string ::LALH5Dataset
1092 * @details
1093 * Creates a new HDF5 dataset with name @p name within a HDF5 file
1094 * associated with the ::LALH5File @p file structure and allocates a
1095 * ::LALH5Dataset structure associated with the dataset. The type
1096 * of data to be stored in the dataset is variable length strings
1097 * and the number of strings in the dataset is given by the @p length
1098 * parameter.
1099 *
1100 * The ::LALH5File @p file passed to this routine must be a file
1101 * opened for writing.
1102 *
1103 * @param file Pointer to a ::LALH5File structure in which to create the dataset.
1104 * @param name Pointer to a string with the name of the dataset to create.
1105 * @param length The number of variable length strings in the dataset.
1106 * @returns A pointer to a ::LALH5Dataset structure associated with the
1107 * specified dataset within a HDF5 file.
1108 * @retval NULL An error occurred creating the dataset.
1109 */
1110LALH5Dataset * XLALH5DatasetAllocStringData(LALH5File UNUSED *file, const char UNUSED *name, size_t UNUSED length)
1111{
1112#ifndef HAVE_HDF5
1113 XLAL_ERROR_NULL(XLAL_EFAILED, "HDF5 support not implemented");
1114#else
1115 LALH5Dataset *dset;
1116 hsize_t npoints = length;
1117 size_t namelen;
1118
1119 if (name == NULL || file == NULL)
1121 if (file->mode != LAL_H5_FILE_MODE_WRITE)
1122 XLAL_ERROR_NULL(XLAL_EINVAL, "Attempting to write to a read-only HDF5 file");
1123
1124 namelen = strlen(name);
1125 dset = LALCalloc(1, sizeof(*dset) + namelen + 1); /* use flexible array member to record name */
1126 if (!dset)
1128
1129 /* create datatype; here we use ASCII encoding */
1130 dset->dtype_id = threadsafe_H5Tcopy(H5T_C_S1);
1131 if (dset->dtype_id < 0) {
1132 LALFree(dset);
1133 XLAL_ERROR_NULL(XLAL_EIO, "Could not copy datatype");
1134 }
1135 if (threadsafe_H5Tset_size(dset->dtype_id, H5T_VARIABLE) < 0) {
1136 threadsafe_H5Tclose(dset->dtype_id);
1137 LALFree(dset);
1138 XLAL_ERROR_NULL(XLAL_EIO, "Could not set datatype size");
1139 }
1140
1141 /* create dataspace */
1142 dset->space_id = threadsafe_H5Screate_simple(1, &npoints, NULL);
1143 if (dset->space_id < 0) {
1144 threadsafe_H5Tclose(dset->dtype_id);
1145 LALFree(dset);
1146 XLAL_ERROR_NULL(XLAL_EIO, "Could not create dataspace for dataset `%s'", name);
1147 }
1148
1149 /* create dataset */
1150 dset->dataset_id = threadsafe_H5Dcreate2(file->file_id, name, dset->dtype_id, dset->space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
1151 if (dset->dataset_id < 0) {
1152 threadsafe_H5Tclose(dset->dtype_id);
1153 threadsafe_H5Sclose(dset->space_id);
1154 LALFree(dset);
1155 XLAL_ERROR_NULL(XLAL_EIO, "Could not create dataset `%s'", name);
1156 }
1157
1158 /* record name of dataset and parent id */
1159 snprintf(dset->name, namelen + 1, "%s", name);
1160 dset->parent_id = file->file_id;
1161
1162 return dset;
1163#endif
1164}
1165
1166/**
1167 * @brief Writes data to a ::LALH5Dataset
1168 * @details
1169 * Writes the data contained in @p data to a HDF5 dataset associated
1170 * with the ::LALH5Dataset @p dset structure.
1171 * @param dset Pointer to a ::LALH5Dataset structure to which to write the data.
1172 * @param data Pointer to the data buffer to be written.
1173 * @retval 0 Success.
1174 * @retval -1 Failure.
1175 */
1176int XLALH5DatasetWrite(LALH5Dataset UNUSED *dset, void UNUSED *data)
1177{
1178#ifndef HAVE_HDF5
1179 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1180#else
1181 if (dset == NULL || data == NULL)
1183 if (threadsafe_H5Dwrite(dset->dataset_id, dset->dtype_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, data) < 0)
1184 XLAL_ERROR(XLAL_EIO, "Could not write data to dataset");
1185 return 0;
1186#endif
1187}
1188
1189/**
1190 * @brief Reads a ::LALH5Dataset
1191 * @details
1192 * Opens an existing HDF5 dataset with name @p name within a HDF5 file
1193 * associated with the ::LALH5File @p file structure and allocates a
1194 * ::LALH5Dataset structure associated with the dataset.
1195 *
1196 * The ::LALH5File @p file passed to this routine must be a file
1197 * opened for reading.
1198 *
1199 * @param file Pointer to a ::LALH5File structure containing the dataset
1200 * to be opened.
1201 * @param name Pointer to a string with the name of the dataset to open.
1202 * @returns A pointer to a ::LALH5Dataset structure associated with the
1203 * specified dataset within a HDF5 file.
1204 * @retval NULL An error occurred creating the dataset.
1205 */
1206LALH5Dataset * XLALH5DatasetRead(LALH5File UNUSED *file, const char UNUSED *name)
1207{
1208#ifndef HAVE_HDF5
1209 XLAL_ERROR_NULL(XLAL_EFAILED, "HDF5 support not implemented");
1210#else
1211 hid_t dtype_id;
1212 LALH5Dataset *dset;
1213 size_t namelen;
1214 if (name == NULL || file == NULL)
1216 if (file->mode != LAL_H5_FILE_MODE_READ)
1217 XLAL_ERROR_NULL(XLAL_EINVAL, "Attempting to read a write-only HDF5 file");
1218
1219 namelen = strlen(name);
1220 dset = LALCalloc(1, sizeof(*dset) + namelen + 1); /* use flexible array member to record name */
1221 if (!dset)
1223
1224 dset->dataset_id = threadsafe_H5Dopen2(file->file_id, name, H5P_DEFAULT);
1225 if (dset->dataset_id < 0) {
1226 LALFree(dset);
1227 XLAL_ERROR_NULL(XLAL_EIO, "Could not read dataset `%s'", name);
1228 }
1229
1230 dset->space_id = threadsafe_H5Dget_space(dset->dataset_id);
1231 if (dset->space_id < 0) {
1232 LALFree(dset);
1233 XLAL_ERROR_NULL(XLAL_EIO, "Could not read dataspace of dataset `%s'", name);
1234 }
1235
1236 dtype_id = threadsafe_H5Dget_type(dset->dataset_id);
1237 if (dtype_id < 0) {
1238 threadsafe_H5Sclose(dset->space_id);
1239 LALFree(dset);
1240 XLAL_ERROR_NULL(XLAL_EIO, "Could not read datatype of dataset `%s'", name);
1241 }
1242
1243 /* convert type to native type */
1244 dset->dtype_id = threadsafe_H5Tget_native_type(dtype_id, H5T_DIR_ASCEND);
1245 threadsafe_H5Tclose(dtype_id);
1246 if (dset->dtype_id < 0) {
1247 threadsafe_H5Sclose(dset->space_id);
1248 LALFree(dset);
1249 XLAL_ERROR_NULL(XLAL_EIO, "Could not get native type for dataset `%s'", name);
1250 }
1251
1252 /* record name of dataset and parent id */
1253 snprintf(dset->name, namelen + 1, "%s", name);
1254 dset->parent_id = file->file_id;
1255 return dset;
1256#endif
1257}
1258
1259/**
1260 * @brief Checks if a ::LALH5Dataset contains variable length string data
1261 * @param dset Pointer to a ::LALH5Dataset to be checked.
1262 * @retval 1 ::LALH5Dataset is of variable length string type
1263 * @retval 0 ::LALH5Dataset is not of variable length string type
1264 * @retval -1 Failure.
1265 */
1267{
1268#ifndef HAVE_HDF5
1269 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1270#else
1271 int retval;
1272 retval = threadsafe_H5Tget_class(dset->dtype_id);
1273 XLAL_CHECK(retval >= 0, XLAL_EIO);
1274 if (retval == H5T_STRING) {
1275 retval = threadsafe_H5Tis_variable_str(dset->dtype_id);
1276 XLAL_CHECK(retval >= 0, XLAL_EIO);
1277 if (retval) {
1278 retval = threadsafe_H5Tget_strpad(dset->dtype_id);
1279 XLAL_CHECK(retval >= 0, XLAL_EIO);
1280 if (retval == H5T_STR_NULLTERM)
1281 return 1;
1282 }
1283 }
1284 return 0;
1285#endif
1286}
1287
1288/**
1289 * @brief Checks if a ::LALH5Dataset contains fixed length string data
1290 * @param dset Pointer to a ::LALH5Dataset to be checked.
1291 * @retval 1 ::LALH5Dataset is of fixed length string type
1292 * @retval 0 ::LALH5Dataset is not of fixed length string type
1293 * @retval -1 Failure.
1294 */
1296{
1297#ifndef HAVE_HDF5
1298 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1299#else
1300 int retval;
1301 retval = threadsafe_H5Tget_class(dset->dtype_id);
1302 XLAL_CHECK(retval >= 0, XLAL_EIO);
1303 if (retval == H5T_STRING) {
1304 retval = threadsafe_H5Tis_variable_str(dset->dtype_id);
1305 XLAL_CHECK(retval >= 0, XLAL_EIO);
1306 if (!retval) {
1307 retval = threadsafe_H5Tget_strpad(dset->dtype_id);
1308 XLAL_CHECK(retval >= 0, XLAL_EIO);
1309 switch (retval) {
1310 case H5T_STR_NULLTERM:
1311 case H5T_STR_NULLPAD:
1312 return 1;
1313 default:
1314 break;
1315 }
1316 }
1317 }
1318 return 0;
1319#endif
1320}
1321
1322/**
1323 * @brief Gets the number of points in a ::LALH5Dataset
1324 * @param dset Pointer to a ::LALH5Dataset to be queried.
1325 * @returns The number of points in the HDF5 dataset associated
1326 * with the specified ::LALH5Dataset.
1327 * @retval (size_t)(-1) Failure.
1328 */
1330{
1331#ifndef HAVE_HDF5
1332 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1333#else
1334 hssize_t npoints;
1335 if (dset == NULL)
1337 npoints = threadsafe_H5Sget_simple_extent_npoints(dset->space_id);
1338 if (npoints < 0)
1339 XLAL_ERROR(XLAL_EIO, "Could not read number of points in dataspace");
1340 return npoints;
1341#endif
1342}
1343
1344/**
1345 * @brief Gets the number of bytes in a ::LALH5Dataset
1346 * @param dset Pointer to a ::LALH5Dataset to be queried.
1347 * @returns The number of bytes in the HDF5 dataset associated
1348 * with the specified ::LALH5Dataset. This is the number of
1349 * bytes required to hold the data in that dataset.
1350 * @retval (size_t)(-1) Failure.
1351 */
1353{
1354#ifndef HAVE_HDF5
1355 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1356#else
1357 size_t size;
1358 size_t npoints;
1359 if (dset == NULL)
1361 size = threadsafe_H5Tget_size(dset->dtype_id);
1362 if (size == 0)
1363 XLAL_ERROR(XLAL_EIO, "Could not read size of datatype");
1364 npoints = XLALH5DatasetQueryNPoints(dset);
1365 if (npoints == (size_t)(-1))
1367 return size * npoints;
1368#endif
1369}
1370
1371/**
1372 * @brief Gets the type of data in a ::LALH5Dataset
1373 * @param dset Pointer to a ::LALH5Dataset to be queried.
1374 * @returns The \c LALTYPECODE of the datatype in the
1375 * HDF5 dataset associated with the specified ::LALH5Dataset.
1376 * @retval -1 Failure.
1377 */
1379{
1380#ifndef HAVE_HDF5
1381 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1382#else
1383 LALTYPECODE dtype;
1384 if (dset == NULL)
1386 dtype = XLALTypeFromH5Type(dset->dtype_id);
1387 if ((int)dtype < 0)
1389 return dtype;
1390#endif
1391}
1392
1393/**
1394 * @brief Gets the number of dimensions of the dataspace in a ::LALH5Dataset
1395 * @param dset Pointer to a ::LALH5Dataset to be queried.
1396 * @returns The number of dimensions in the dataspace in the
1397 * HDF5 dataset associated with the specified ::LALH5Dataset.
1398 * @retval -1 Failure.
1399 */
1401{
1402#ifndef HAVE_HDF5
1403 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1404#else
1405 int rank;
1406 if (dset == NULL)
1408 rank = threadsafe_H5Sget_simple_extent_ndims(dset->space_id);
1409 if (rank < 0)
1410 XLAL_ERROR(XLAL_EIO, "Could not read rank of dataset");
1411 return rank;
1412#endif
1413}
1414
1415/**
1416 * @brief Gets the dimensions of the dataspace in a ::LALH5Dataset
1417 * @param dset Pointer to a ::LALH5Dataset to be queried.
1418 * @returns A pointer to a newly-allocated UINT4Vector containing
1419 * the dimensions of the dataspace in the HDF5 dataset associated
1420 * with the * specified ::LALH5Dataset.
1421 * @retval NULL Failure.
1422 */
1424{
1425#ifndef HAVE_HDF5
1426 XLAL_ERROR_NULL(XLAL_EFAILED, "HDF5 support not implemented");
1427#else
1428 UINT4Vector *dimLength;
1429 hsize_t *dims;
1430 int rank;
1431 int dim;
1432
1433 if (dset == NULL)
1435
1436 rank = XLALH5DatasetQueryNDim(dset);
1437 if (rank < 0)
1439
1440 dims = LALCalloc(rank, sizeof(*dims));
1441 if (threadsafe_H5Sget_simple_extent_dims(dset->space_id, dims, NULL) < 0) {
1442 LALFree(dims);
1443 XLAL_ERROR_NULL(XLAL_EIO, "Could not read dimensions of dataspace");
1444 }
1445
1446 dimLength = XLALCreateUINT4Vector(rank);
1447 if (dimLength == NULL) {
1448 LALFree(dims);
1450 }
1451
1452 for (dim = 0; dim < rank; ++dim)
1453 dimLength->data[dim] = dims[dim];
1454 LALFree(dims);
1455
1456 return dimLength;
1457#endif
1458}
1459
1460/* LALMalloc and LALFree hooks to give to HDF5 library for memory allocation */
1461#ifdef HAVE_HDF5
1462static void *lal_malloc_hook(size_t size, void UNUSED *alloc_info)
1463{
1464 return XLALMalloc(size);
1465}
1466static void lal_free_hook(void *mem, void UNUSED *free_info)
1467{
1468 XLALFree(mem);
1469 return;
1470}
1471#endif
1472
1473/**
1474 * @brief Gets the data contained in a ::LALH5Dataset
1475 * @details
1476 * This routine reads data from a HDF5 dataset associated with
1477 * the ::LALH5Dataset @p dset and stores the data in the buffer
1478 * @p data. This buffer should be sufficiently large to hold
1479 * the entire contents of the dataset; this size can be determined
1480 * with the routine XLALH5DatasetQueryNBytes().
1481 * If the dataset contains variable-length string data, @p data
1482 * should instead be a pointer to an array of length npoints of
1483 * char* pointers where npoints can be determined with the
1484 * routine XLALH5DatasetQueryNPoints(). In this case, each of the npoints
1485 * strings will be allocated using LALMalloc().
1486 * @param data Pointer to a memory in which to store the data.
1487 * @param dset Pointer to a ::LALH5Dataset from which to extract the data.
1488 * @retval 0 Success.
1489 * @retval -1 Failure.
1490 */
1491int XLALH5DatasetQueryData(void UNUSED *data, LALH5Dataset UNUSED *dset)
1492{
1493#ifndef HAVE_HDF5
1494 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1495#else
1496 int isstrdata;
1497 hid_t plist;
1498 if (data == NULL || dset == NULL)
1500 isstrdata = XLALH5DatasetCheckStringData(dset);
1501 if (isstrdata < 0)
1503 if (isstrdata) {
1504 /* string data: tell HDF5 library to use LALMalloc */
1505 plist = threadsafe_H5Pcreate(H5P_DATASET_XFER);
1506 if (plist < 0)
1507 XLAL_ERROR(XLAL_EIO, "Could not create property list");
1508 if (threadsafe_H5Pset_vlen_mem_manager(plist, lal_malloc_hook, NULL, lal_free_hook, NULL) < 0) {
1509 threadsafe_H5Pclose(plist);
1510 XLAL_ERROR(XLAL_EIO, "Could not set memory manager");
1511 }
1512 } else { /* not string data */
1513 plist = threadsafe_H5Pcopy(H5P_DEFAULT);
1514 if (plist < 0)
1515 XLAL_ERROR(XLAL_EIO, "Could not create property list");
1516 }
1517 if (threadsafe_H5Dread(dset->dataset_id, dset->dtype_id, H5S_ALL, H5S_ALL, plist, data) < 0) {
1518 threadsafe_H5Pclose(plist);
1519 XLAL_ERROR(XLAL_EIO, "Could not read data from dataset");
1520 }
1521 threadsafe_H5Pclose(plist);
1522 return 0;
1523#endif
1524}
1525
1526/** @} */
1527
1528/**
1529 * @name Attribute Routines
1530 * @anchor attribute_routines
1531 * @details
1532 * These routines allow for reading or writing attributes to ::LALH5File
1533 * or ::LALH5Dataset objects. To use these, the pointer to the object
1534 * should be cast to a \c LALH5Generic type as in the following example.
1535 * @code
1536 * LALH5File *file = XLALH5FileOpen("example.h5", "r");
1537 * LALH5Dataset *dset = XLALH5DatasetRead(file, "example_dataset");
1538 * size_t num_file_attrs;
1539 * size_t num_dset_attrs;
1540 * num_file_attrs = XLALH5AttributeQueryN((LALH5Generic)file);
1541 * num_dset_attrs = XLALH5AttributeQueryN((LALH5Generic)dset);
1542 * @endcode
1543 * @{
1544 */
1545
1546
1547/**
1548 * @brief Checks for existence of an attribute associated with a ::LALH5File
1549 * or ::LALH5Dataset
1550 * @details
1551 * Checks if there is an attribute with name @p name associated with
1552 * an HDF5 object @p object that is either a ::LALH5File or
1553 * ::LALH5Dataset.
1554 * If the attribute exists the return code is 1;
1555 * if the dataset does not exist a return code value of 0 is used.
1556 *
1557 * @attention Read failure results in a returned value of 0.
1558 *
1559 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to check for
1560 * attribute.
1561 * @param name Pointer to a string with the name of the attribute to check.
1562 * @retval 0 Attribute does not exist or failure.
1563 * @retval 1 Attribute exists.
1564 */
1565size_t XLALH5AttributeCheckExists(const LALH5Generic UNUSED object, const char UNUSED *name)
1566{
1567#ifndef HAVE_HDF5
1568 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1569#else
1570 hid_t obj_id;
1571 H5O_info_t obj_info;
1572 hsize_t i;
1573
1574 obj_id = object.generic->object_id;
1575 if (obj_id < 0)
1577
1578 if (threadsafe_H5Oget_info(obj_id, &obj_info) < 0)
1579 XLAL_ERROR_VAL(0, XLAL_EIO, "Could not get HDF5 object info");
1580
1581 for (i = 0; i < obj_info.num_attrs; ++i) {
1582 hid_t attr_id;
1583 int n;
1584
1585 attr_id = threadsafe_H5Aopen_idx(obj_id, i);
1586 if (attr_id < 0)
1587 XLAL_ERROR_VAL(0, XLAL_EIO, "Could not read attribute");
1588
1589 n = threadsafe_H5Aget_name(attr_id, 0, NULL);
1590 if (n < 0) {
1591 threadsafe_H5Aclose(attr_id);
1592 XLAL_ERROR_VAL(0, XLAL_EIO, "Could not read attribute name");
1593 }
1594 char attr_name[n + 1];
1595 n = threadsafe_H5Aget_name(attr_id, n + 1, attr_name);
1596 threadsafe_H5Aclose(attr_id);
1597 if (n < 0)
1598 XLAL_ERROR_VAL(0, XLAL_EIO, "Could not read attribute name");
1599 if (strcmp(name, attr_name) == 0)
1600 return 1; /* found it */
1601 }
1602
1603 /* no matching attribute found */
1604 return 0;
1605#endif
1606}
1607
1608/**
1609 * @brief Gets the number of attributes associated with a ::LALH5File
1610 * or ::LALH5Dataset
1611 * @details
1612 * This routines returns the number of attributes associated with
1613 * an HDF5 object @p object that is either a ::LALH5File or
1614 * ::LALH5Dataset.
1615 *
1616 * @param object Pointer to a ::LALH5File or ::LALH5Dataset that will be
1617 * queried.
1618 * @returns The number of attributes associated with the object.
1619 * @retval -1 Failure.
1620 */
1621size_t XLALH5AttributeQueryN(const LALH5Generic UNUSED object)
1622{
1623#ifndef HAVE_HDF5
1624 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1625#else
1626 hid_t obj_id;
1627 H5O_info_t obj_info;
1628
1629 obj_id = object.generic->object_id;
1630 if (obj_id < 0)
1632
1633 if (threadsafe_H5Oget_info(obj_id, &obj_info) < 0)
1634 XLAL_ERROR(XLAL_EIO, "Could not get HDF5 object info");
1635
1636 return obj_info.num_attrs;
1637#endif
1638}
1639
1640/**
1641 * @brief Gets the name of an attribute associated with a ::LALH5File
1642 * or ::LALH5Dataset
1643 * @details
1644 * This routines gets the name of an attributes associated with
1645 * an HDF5 object @p object that is either a ::LALH5File or
1646 * ::LALH5Dataset.
1647 * The index @p pos identifies which attribute's name is returned.
1648 * The result is written into the buffer pointed to by @p name, the size
1649 * of which is @p size bytes. If @p name is NULL, no data is copied but
1650 * the routine returns the length of the string. Therefore, this routine
1651 * can be called once to determine the amount of memory required, the
1652 * memory can be allocated, and then it can be called a second time to
1653 * read the string. If the parameter @p size is less than or equal to
1654 * the string length then only $p size-1 bytes of the string are copied
1655 * to the buffer @p name.
1656 * @note The return value is the length of the string, not including the
1657 * terminating NUL character; thus the buffer @p name should be allocated
1658 * to be one byte larger.
1659 * @param name Pointer to a buffer into which the string will be written.
1660 * @param size Size in bytes of the buffer into which the string will be
1661 * written.
1662 * @param object Pointer to a ::LALH5File or ::LALH5Dataset that will be
1663 * queried.
1664 * @param pos The index identifying which attribute associated with the object.
1665 * @retval 0 Success.
1666 * @retval -1 Failure.
1667 */
1668int XLALH5AttributeQueryName(char UNUSED *name, size_t UNUSED size, const LALH5Generic UNUSED object, int UNUSED pos)
1669{
1670#ifndef HAVE_HDF5
1671 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1672#else
1673 hid_t obj_id;
1674 hid_t attr_id;
1675 H5O_info_t obj_info;
1676 int n;
1677
1678 obj_id = object.generic->object_id;
1679 if (obj_id < 0)
1681
1682 if (threadsafe_H5Oget_info(obj_id, &obj_info) < 0)
1683 XLAL_ERROR(XLAL_EIO, "Could not get HDF5 object info");
1684
1685 if ((hsize_t)pos >= obj_info.num_attrs)
1686 XLAL_ERROR(XLAL_EINVAL, "No attribute associated with given position");
1687
1688 attr_id = threadsafe_H5Aopen_idx(obj_id, pos);
1689 if (attr_id < 0)
1690 XLAL_ERROR(XLAL_EIO, "Could not read attribute");
1691
1692 n = threadsafe_H5Aget_name(attr_id, size, name);
1693 threadsafe_H5Aclose(attr_id);
1694 if (n < 0)
1695 XLAL_ERROR(XLAL_EIO, "Could not read attribute name");
1696
1697 return n;
1698#endif
1699}
1700
1701/**
1702 * @brief Adds a scalar attribute to a ::LALH5File or ::LALH5Dataset
1703 * @details
1704 * This routine adds a scalar-valued attribute with name @p key
1705 * and value given by the memory addressed by @p value to a
1706 * HDF5 object associated with the ::LALH5File or ::LALH5Dataset
1707 * @p object.
1708 * The data type of the scalar value is given by the \c LALTYPECODE
1709 * @p dtype.
1710 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to which the attribute
1711 * will be added.
1712 * @param key Pointer to a string with the name of the new attribute.
1713 * @param value Pointer to the value of the scalar attribute to be added.
1714 * @param dtype \c LALTYPECODE value specifying the data type of the attribute.
1715 * @retval 0 Success.
1716 * @retval -1 Failure.
1717 */
1718int XLALH5AttributeAddScalar(LALH5Generic UNUSED object, const char UNUSED *key, const void UNUSED *value, LALTYPECODE UNUSED dtype)
1719{
1720#ifndef HAVE_HDF5
1721 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1722#else
1723 hid_t obj_id;
1724 hid_t attr_id;
1725 hid_t space_id;
1726 hid_t dtype_id;
1727
1728 obj_id = object.generic->object_id;
1729 if (obj_id < 0)
1731
1732 dtype_id = XLALH5TypeFromLALType(dtype);
1733 if (dtype_id < 0)
1735
1736 space_id = threadsafe_H5Screate(H5S_SCALAR);
1737 if (space_id < 0) {
1738 threadsafe_H5Tclose(dtype_id);
1739 XLAL_ERROR(XLAL_EIO, "Could not create dataspace for attribute `%s'", key);
1740 }
1741
1742 attr_id = threadsafe_H5Acreate2(obj_id, key, dtype_id, space_id, H5P_DEFAULT, H5P_DEFAULT);
1743 threadsafe_H5Sclose(space_id);
1744 if (attr_id < 0) {
1745 threadsafe_H5Tclose(dtype_id);
1746 XLAL_ERROR(XLAL_EIO, "Could not create attribute `%s'", key);
1747 }
1748
1749 if (threadsafe_H5Awrite(attr_id, dtype_id, value) < 0) {
1750 threadsafe_H5Aclose(attr_id);
1751 threadsafe_H5Tclose(dtype_id);
1752 XLAL_ERROR(XLAL_EIO, "Could not write attribute `%s'", key);
1753 }
1754
1755 threadsafe_H5Aclose(attr_id);
1756 threadsafe_H5Tclose(dtype_id);
1757 return 0;
1758#endif
1759}
1760
1761/**
1762 * @brief Adds a string attribute to a ::LALH5File or ::LALH5Dataset
1763 * @details
1764 * This routine adds a NUL-terminated variable-length string @p value
1765 * attribute with name @p key to a HDF5 object associated with the
1766 * ::LALH5File or ::LALH5Dataset @p object.
1767 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to which the
1768 * attribute will be added.
1769 * @param key Pointer to a string with the name of the new attribute.
1770 * @param value Pointer to a string with the value of the new attribute.
1771 * @retval 0 Success.
1772 * @retval -1 Failure.
1773 */
1774int XLALH5AttributeAddString(LALH5Generic UNUSED object, const char UNUSED *key, const char UNUSED *value)
1775{
1776#ifndef HAVE_HDF5
1777 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1778#else
1779 hid_t obj_id;
1780 hid_t attr_id;
1781 hid_t space_id;
1782 hid_t dtype_id;
1783
1784 obj_id = object.generic->object_id;
1785 if (obj_id < 0)
1787
1788 dtype_id = threadsafe_H5Tcopy(H5T_C_S1);
1789 if (dtype_id < 0)
1790 XLAL_ERROR(XLAL_EIO, "Could not create datatype for attribure `%s'", key);
1791 if (threadsafe_H5Tset_size(dtype_id, H5T_VARIABLE) < 0)
1792 {
1793 threadsafe_H5Tclose(dtype_id);
1794 XLAL_ERROR(XLAL_EIO, "Could not create datatype for attribure `%s'", key);
1795 }
1796
1797 space_id = threadsafe_H5Screate(H5S_SCALAR);
1798 if (space_id < 0) {
1799 threadsafe_H5Tclose(dtype_id);
1800 XLAL_ERROR(XLAL_EIO, "Could not create dataspace for attribute `%s'", key);
1801 }
1802
1803 attr_id = threadsafe_H5Acreate2(obj_id, key, dtype_id, space_id, H5P_DEFAULT, H5P_DEFAULT);
1804 threadsafe_H5Sclose(space_id);
1805 if (attr_id < 0) {
1806 threadsafe_H5Tclose(dtype_id);
1807 XLAL_ERROR(XLAL_EIO, "Could not create attribute `%s'", key);
1808 }
1809
1810 if (threadsafe_H5Awrite(attr_id, dtype_id, &value) < 0) {
1811 threadsafe_H5Aclose(attr_id);
1812 threadsafe_H5Tclose(dtype_id);
1813 XLAL_ERROR(XLAL_EIO, "Could not write attribute `%s'", key);
1814 }
1815
1816 threadsafe_H5Aclose(attr_id);
1817 threadsafe_H5Tclose(dtype_id);
1818 return 0;
1819#endif
1820}
1821
1822/**
1823 * @brief Adds a LIGOTimeGPS attribute to a ::LALH5File or ::LALH5Dataset
1824 * @details
1825 * This routine adds a LIGOTimeGPS @p value attribute with name @p key to a
1826 * HDF5 object associated with the ::LALH5File or ::LALH5Dataset @p object.
1827 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to which the
1828 * attribute will be added.
1829 * @param key Pointer to a string with the name of the new attribute.
1830 * @param value Pointer to a LIGOTimeGPS structure with the value of the new
1831 * attribute.
1832 * @retval 0 Success.
1833 * @retval -1 Failure.
1834 */
1835int XLALH5AttributeAddLIGOTimeGPS(LALH5Generic UNUSED object, const char UNUSED *key, const LIGOTimeGPS UNUSED *value)
1836{
1837#ifndef HAVE_HDF5
1838 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1839#else
1840 hid_t obj_id;
1841 hid_t attr_id;
1842 hid_t space_id;
1843 hid_t dtype_id;
1844
1845 obj_id = object.generic->object_id;
1846 if (obj_id < 0)
1848
1849 dtype_id = XLALH5TypeNativeLIGOTimeGPS();
1850 if (dtype_id < 0)
1852
1853 space_id = threadsafe_H5Screate(H5S_SCALAR);
1854 if (space_id < 0) {
1855 threadsafe_H5Tclose(dtype_id);
1856 XLAL_ERROR(XLAL_EIO, "Could not create dataspace for attribute `%s'", key);
1857 }
1858
1859 attr_id = threadsafe_H5Acreate2(obj_id, key, dtype_id, space_id, H5P_DEFAULT, H5P_DEFAULT);
1860 threadsafe_H5Sclose(space_id);
1861 if (attr_id < 0) {
1862 threadsafe_H5Tclose(dtype_id);
1863 XLAL_ERROR(XLAL_EIO, "Could not create attribute `%s'", key);
1864 }
1865
1866 if (threadsafe_H5Awrite(attr_id, dtype_id, value) < 0) {
1867 threadsafe_H5Aclose(attr_id);
1868 threadsafe_H5Tclose(dtype_id);
1869 XLAL_ERROR(XLAL_EIO, "Could not write attribute `%s'", key);
1870 }
1871
1872 threadsafe_H5Aclose(attr_id);
1873 threadsafe_H5Tclose(dtype_id);
1874 return 0;
1875#endif
1876}
1877
1878/**
1879 * @brief Adds a 1d enum array attribute to a ::LALH5File or ::LALH5Dataset
1880 * @details
1881 * This routine adds the 1d enum array @p value of length @p length attribute
1882 * with name @p key to a HDF5 object associated with the ::LALH5File or
1883 * ::LALH5Dataset @p object.
1884 * The names and values of the @p nenum enumeration constants are provided
1885 * in the arrays @p enumnames and @p enumvals respectively.
1886 *
1887 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to which the
1888 * attribute will be added.
1889 * @param enumnames Pointer to an array of names of the enum constants.
1890 * @param enumvals Pointer to an array of values of the enum constants.
1891 * @param nenum Number of enum constants.
1892 * @param key Pointer to a string with the name of the new attribute.
1893 * @param value Pointer to an array of enum values.
1894 * @param length Length of the array of enum values.
1895 * @retval 0 Success.
1896 * @retval -1 Failure.
1897 */
1898int XLALH5AttributeAddEnumArray1D(LALH5Generic UNUSED object, const char UNUSED *enumnames[], const int UNUSED enumvals[], size_t UNUSED nenum, const char UNUSED *key, const int UNUSED value[], size_t UNUSED length)
1899{
1900#ifndef HAVE_HDF5
1901 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1902#else
1903 hsize_t dims[] = {length};
1904 hid_t obj_id;
1905 hid_t attr_id;
1906 hid_t space_id;
1907 hid_t edtype_id;
1908 hid_t adtype_id;
1909
1910 obj_id = object.generic->object_id;
1911 if (obj_id < 0)
1913
1914 edtype_id = XLALH5TypeEnum(enumnames, enumvals, nenum);
1915 if (edtype_id < 0)
1916 XLAL_ERROR(XLAL_EFUNC, "Could not create enum type for attribute `%s'", key);
1917
1918 adtype_id = threadsafe_H5Tarray_create2(edtype_id, 1, dims);
1919 threadsafe_H5Tclose(edtype_id);
1920 if (adtype_id < 0)
1921 XLAL_ERROR(XLAL_EIO, "Could not create array type for attribute `%s'", key);
1922
1923 space_id = threadsafe_H5Screate(H5S_SCALAR);
1924 if (space_id < 0) {
1925 threadsafe_H5Tclose(adtype_id);
1926 XLAL_ERROR(XLAL_EIO, "Could not create dataspace for attribute `%s'", key);
1927 }
1928
1929 attr_id = threadsafe_H5Acreate2(obj_id, key, adtype_id, space_id, H5P_DEFAULT, H5P_DEFAULT);
1930 threadsafe_H5Sclose(space_id);
1931 if (attr_id < 0) {
1932 threadsafe_H5Tclose(adtype_id);
1933 XLAL_ERROR(XLAL_EIO, "Could not create attribute `%s'", key);
1934 }
1935
1936 if (threadsafe_H5Awrite(attr_id, adtype_id, value) < 0) {
1937 threadsafe_H5Aclose(attr_id);
1938 threadsafe_H5Tclose(adtype_id);
1939 XLAL_ERROR(XLAL_EIO, "Could not write attribute `%s'", key);
1940 }
1941
1942 threadsafe_H5Aclose(attr_id);
1943 threadsafe_H5Tclose(adtype_id);
1944 return 0;
1945#endif
1946}
1947
1948/**
1949 * @brief Gets the datatype of an attribute in a ::LALH5File or ::LALH5Dataset
1950 * @details
1951 * This routine queries the datatype of a scalar attribute with
1952 * name @p key in a HDF5 object associated with the ::LALH5File or ::LALH5Dataset
1953 * @p object.
1954 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to be queried.
1955 * @param key Pointer to a string with the name of the attribute to query.
1956 * @returns \c LALTYPECODE value of the datatype of the scalar attribute.
1957 * @retval -1 Failure.
1958 */
1959LALTYPECODE XLALH5AttributeQueryScalarType(const LALH5Generic UNUSED object, const char UNUSED *key)
1960{
1961#ifndef HAVE_HDF5
1962 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
1963#else
1964 LALTYPECODE dtype;
1965 hid_t obj_id;
1966 hid_t attr_id;
1967 hid_t space_id;
1968 hid_t dtype_id;
1969 hid_t memtype_id;
1970
1971 obj_id = object.generic->object_id;
1972 if (obj_id < 0)
1974
1975 attr_id = threadsafe_H5Aopen(obj_id, key, H5P_DEFAULT);
1976 if (attr_id < 0)
1977 XLAL_ERROR(XLAL_EIO, "Could not read attribute `%s'", key);
1978
1979 /* sanity check: make sure this is a scalar attribute */
1980 space_id = threadsafe_H5Aget_space(attr_id);
1981 if (space_id < 0) {
1982 threadsafe_H5Aclose(attr_id);
1983 XLAL_ERROR(XLAL_EIO, "Could not read dataspace of attribute `%s'", key);
1984 }
1985 if (threadsafe_H5Sget_simple_extent_ndims(space_id) != 0 || threadsafe_H5Sget_simple_extent_npoints(space_id) != 1) {
1986 threadsafe_H5Sclose(space_id);
1987 threadsafe_H5Aclose(attr_id);
1988 XLAL_ERROR(XLAL_EIO, "Attribute `%s' is not a scalar attribute", key);
1989 }
1990
1991 dtype_id = threadsafe_H5Aget_type(attr_id);
1992 threadsafe_H5Aclose(attr_id);
1993 if (attr_id < 0)
1994 XLAL_ERROR(XLAL_EIO, "Could not read type of attribute `%s'", key);
1995
1996 memtype_id = threadsafe_H5Tget_native_type(dtype_id, H5T_DIR_ASCEND);
1997 threadsafe_H5Tclose(dtype_id);
1998 if (memtype_id < 0)
1999 XLAL_ERROR(XLAL_EIO, "Could not get native type of attribute `%s'", key);
2000
2001 dtype = XLALTypeFromH5Type(memtype_id);
2002 threadsafe_H5Tclose(memtype_id);
2003 if ((int)dtype < 0)
2005
2006 return dtype;
2007#endif
2008}
2009
2010/**
2011 * @brief Gets the value of a scalar attribute in a ::LALH5File or ::LALH5Dataset
2012 * @details
2013 * This routine queries the value of a scalar attribute with
2014 * name @p key in a HDF5 object associated with the ::LALH5File or ::LALH5Dataset
2015 * @p object.
2016 * The value is stored in memory pointed to by the pointer @p value.
2017 *
2018 * @attention
2019 * This routine does not allocate memory for @p value. The calling
2020 * routine must ensure that the memory addressed by the pointer @p value
2021 * is sufficient to hold the value in the attribute.
2022 *
2023 * @param value Pointer to memory in which the value will be stored.
2024 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to be queried.
2025 * @param key Pointer to a string with the name of the attribute to query.
2026 * @retval 0 Success.
2027 * @retval -1 Failure.
2028 */
2029int XLALH5AttributeQueryScalarValue(void UNUSED *value, const LALH5Generic UNUSED object, const char UNUSED *key)
2030{
2031#ifndef HAVE_HDF5
2032 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2033#else
2034 hid_t obj_id;
2035 hid_t attr_id;
2036 hid_t space_id;
2037 hid_t dtype_id;
2038 hid_t memtype_id;
2039
2040 obj_id = object.generic->object_id;
2041 if (obj_id < 0)
2043
2044 attr_id = threadsafe_H5Aopen(obj_id, key, H5P_DEFAULT);
2045 if (attr_id < 0)
2046 XLAL_ERROR(XLAL_EIO, "Could not read attribute `%s'", key);
2047
2048 /* sanity check: make sure this is a scalar attribute */
2049 space_id = threadsafe_H5Aget_space(attr_id);
2050 if (space_id < 0) {
2051 threadsafe_H5Aclose(attr_id);
2052 XLAL_ERROR(XLAL_EIO, "Could not read dataspace of attribute `%s'", key);
2053 }
2054 if (threadsafe_H5Sget_simple_extent_ndims(space_id) != 0 || threadsafe_H5Sget_simple_extent_npoints(space_id) != 1) {
2055 threadsafe_H5Sclose(space_id);
2056 threadsafe_H5Aclose(attr_id);
2057 XLAL_ERROR(XLAL_EIO, "Attribute `%s' is not a scalar attribute", key);
2058 }
2059 threadsafe_H5Sclose(space_id);
2060
2061 dtype_id = threadsafe_H5Aget_type(attr_id);
2062 if (dtype_id < 0) {
2063 threadsafe_H5Aclose(attr_id);
2064 XLAL_ERROR(XLAL_EIO, "Could not read type of attribute `%s'", key);
2065 }
2066
2067 memtype_id = threadsafe_H5Tget_native_type(dtype_id, H5T_DIR_ASCEND);
2068 threadsafe_H5Tclose(dtype_id);
2069 if (memtype_id < 0) {
2070 threadsafe_H5Aclose(attr_id);
2071 XLAL_ERROR(XLAL_EIO, "Could not get native type of attribute `%s'", key);
2072 }
2073
2074 if (threadsafe_H5Aread(attr_id, memtype_id, value) < 0) {
2075 threadsafe_H5Tclose(memtype_id);
2076 threadsafe_H5Aclose(attr_id);
2077 XLAL_ERROR(XLAL_EIO, "Could not read data from attribute `%s'", key);
2078 }
2079
2080 threadsafe_H5Tclose(memtype_id);
2081 threadsafe_H5Aclose(attr_id);
2082 return 0;
2083#endif
2084}
2085
2086/**
2087 * @brief Gets the value of a string attribute in a ::LALH5File or ::LALH5Dataset
2088 * @details
2089 * This routine queries the value of a string attribute with
2090 * name @p key in a HDF5 object associated with the ::LALH5File or ::LALH5Dataset
2091 * @p object.
2092 * The result is written into the buffer pointed to by @p value, the size
2093 * of which is @p size bytes. If @p value is NULL, no data is copied but
2094 * the routine returns the length of the string. Therefore, this routine
2095 * can be called once to determine the amount of memory required, the
2096 * memory can be allocated, and then it can be called a second time to
2097 * read the string. If the parameter @p size is less than or equal to
2098 * the string length then only $p size-1 bytes of the string are copied
2099 * to the buffer @p value.
2100 * @note The return value is the length of the string, not including the
2101 * terminating NUL character; thus the buffer @p value should be allocated
2102 * to be one byte larger.
2103 * @param value Pointer to a buffer into which the string will be written.
2104 * @param size Size in bytes of the buffer into which the string will be
2105 * written.
2106 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to be queried.
2107 * @param key Pointer to a string with the name of the attribute to query.
2108 * @returns The number of bytes that would be written to @p value had @p size
2109 * been sufficiently large excluding the terminating NUL byte.
2110 * @retval -1 Failure.
2111 */
2112int XLALH5AttributeQueryStringValue(char UNUSED *value, size_t UNUSED size, const LALH5Generic UNUSED object, const char UNUSED *key)
2113{
2114#ifndef HAVE_HDF5
2115 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2116#else
2117 char *str;
2118 hid_t obj_id;
2119 hid_t attr_id;
2120 hid_t space_id;
2121 hid_t dtype_id;
2122 hid_t memtype_id;
2123 H5T_cset_t cset;
2124 size_t dtype_size;
2125 int vlen;
2126 int n;
2127
2128 obj_id = object.generic->object_id;
2129 if (obj_id < 0)
2131
2132 attr_id = threadsafe_H5Aopen(obj_id, key, H5P_DEFAULT);
2133 if (attr_id < 0)
2134 XLAL_ERROR(XLAL_EIO, "Could not read attribute `%s'", key);
2135
2136 /* sanity check: make sure this is just one string */
2137 space_id = threadsafe_H5Aget_space(attr_id);
2138 if (space_id < 0) {
2139 threadsafe_H5Aclose(attr_id);
2140 XLAL_ERROR(XLAL_EIO, "Could not read dataspace of attribute `%s'", key);
2141 }
2142 if (threadsafe_H5Sget_simple_extent_ndims(space_id) != 0) {
2143 threadsafe_H5Sclose(space_id);
2144 threadsafe_H5Aclose(attr_id);
2145 XLAL_ERROR(XLAL_EIO, "Attribute `%s' is not a string", key);
2146 }
2147
2148 dtype_id = threadsafe_H5Aget_type(attr_id);
2149 if (dtype_id < 0) {
2150 threadsafe_H5Sclose(space_id);
2151 threadsafe_H5Aclose(attr_id);
2152 XLAL_ERROR(XLAL_EIO, "Could not read type of attribute `%s'", key);
2153 }
2154
2155 if (threadsafe_H5Tget_class(dtype_id) != H5T_STRING) {
2156 threadsafe_H5Tclose(dtype_id);
2157 threadsafe_H5Sclose(space_id);
2158 threadsafe_H5Aclose(attr_id);
2159 XLAL_ERROR(XLAL_EIO, "Attribute `%s' is not a string", key);
2160 }
2161
2162 /* FIXME threadsafe */
2163 cset = threadsafe_H5Tget_cset(dtype_id); /* encoding: UTF8 or ASCII */
2164 if (cset < 0) {
2165 threadsafe_H5Tclose(dtype_id);
2166 threadsafe_H5Sclose(space_id);
2167 threadsafe_H5Aclose(attr_id);
2168 XLAL_ERROR(XLAL_EIO, "Could not determine encoding for attribute `%s'", key);
2169 }
2170
2171 vlen = threadsafe_H5Tis_variable_str(dtype_id);
2172 if (vlen < 0) {
2173 threadsafe_H5Tclose(dtype_id);
2174 threadsafe_H5Sclose(space_id);
2175 threadsafe_H5Aclose(attr_id);
2176 XLAL_ERROR(XLAL_EIO, "Could not determine if attribute `%s' is a variable length string", key);
2177 }
2178
2179 if (vlen)
2180 dtype_size = H5T_VARIABLE;
2181 else {
2182 dtype_size = H5Tget_size(dtype_id);
2183 dtype_size++; /* add 1 for null termination */
2184 }
2185
2186 threadsafe_H5Tclose(dtype_id);
2187
2188 memtype_id = threadsafe_H5Tcopy(H5T_C_S1);
2189 if (memtype_id < 0 || threadsafe_H5Tset_size(memtype_id, dtype_size)) {
2190 threadsafe_H5Sclose(space_id);
2191 threadsafe_H5Aclose(attr_id);
2193 }
2194
2195 /* set encoding (UTF8 or ASCII) */
2196 if (threadsafe_H5Tset_cset(memtype_id, cset) < 0) {
2197 threadsafe_H5Tclose(memtype_id);
2198 threadsafe_H5Sclose(space_id);
2199 threadsafe_H5Aclose(attr_id);
2201 }
2202
2203 if (vlen) { /* variable length string */
2204 if (threadsafe_H5Aread(attr_id, memtype_id, &str) < 0) {
2205 threadsafe_H5Tclose(memtype_id);
2206 threadsafe_H5Sclose(space_id);
2207 threadsafe_H5Aclose(attr_id);
2208 XLAL_ERROR(XLAL_EIO, "Could not read data from attribute `%s'", key);
2209 }
2210 n = snprintf(value, value == NULL ? 0 : size, "%s", str);
2211 threadsafe_H5Dvlen_reclaim(memtype_id, space_id, H5P_DEFAULT, &str);
2212 } else {
2213 str = XLALMalloc(dtype_size);
2214 if (threadsafe_H5Aread(attr_id, memtype_id, str) < 0) {
2215 XLALFree(str);
2216 threadsafe_H5Tclose(memtype_id);
2217 threadsafe_H5Sclose(space_id);
2218 threadsafe_H5Aclose(attr_id);
2219 XLAL_ERROR(XLAL_EIO, "Could not read data from attribute `%s'", key);
2220 }
2221 n = snprintf(value, value == NULL ? 0 : size, "%s", str);
2222 XLALFree(str);
2223 }
2224
2225 threadsafe_H5Tclose(memtype_id);
2226 threadsafe_H5Sclose(space_id);
2227 threadsafe_H5Aclose(attr_id);
2228 return n;
2229#endif
2230}
2231
2232/**
2233 * @brief Gets the value of a LIGOTimeGPS attribute in a ::LALH5File or ::LALH5Dataset
2234 * @details
2235 * This routine queries the value of a LIGOTimeGPS attribute with
2236 * name @p key in a HDF5 object associated with the ::LALH5File or ::LALH5Dataset
2237 * @p object.
2238 * The value is stored in memory pointed to by the pointer @p value.
2239 * @param value Pointer to a LIGOTimeGPS structure in which the attribute
2240 * value will be stored.
2241 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to be queried.
2242 * @param key Pointer to a string with the name of the attribute to query.
2243 * @returns Pointer to the LIGOTimeGPS structure passed to this routine.
2244 * @retval NULL Failure.
2245 */
2246LIGOTimeGPS * XLALH5AttributeQueryLIGOTimeGPSValue(LIGOTimeGPS UNUSED *value, const LALH5Generic UNUSED object, const char UNUSED *key)
2247{
2248#ifndef HAVE_HDF5
2249 XLAL_ERROR_NULL(XLAL_EFAILED, "HDF5 support not implemented");
2250#else
2251 char *s;
2252 hid_t obj_id;
2253 hid_t attr_id;
2254 hid_t space_id;
2255 hid_t dtype_id;
2256 hid_t memtype_id;
2257
2258 obj_id = object.generic->object_id;
2259 if (obj_id < 0)
2261
2262 attr_id = threadsafe_H5Aopen(obj_id, key, H5P_DEFAULT);
2263 if (attr_id < 0)
2264 XLAL_ERROR_NULL(XLAL_EIO, "Could not read attribute `%s'", key);
2265
2266 /* sanity check: make sure this is a scalar attribute */
2267 space_id = threadsafe_H5Aget_space(attr_id);
2268 if (space_id < 0) {
2269 threadsafe_H5Aclose(attr_id);
2270 XLAL_ERROR_NULL(XLAL_EIO, "Could not read dataspace of attribute `%s'", key);
2271 }
2272 if (threadsafe_H5Sget_simple_extent_ndims(space_id) != 0 || threadsafe_H5Sget_simple_extent_npoints(space_id) != 1) {
2273 threadsafe_H5Sclose(space_id);
2274 threadsafe_H5Aclose(attr_id);
2275 XLAL_ERROR_NULL(XLAL_EIO, "Attribute `%s' is not a scalar attribute", key);
2276 }
2277 threadsafe_H5Sclose(space_id);
2278
2279 /* sanity check the dtype_id */
2280
2281 dtype_id = threadsafe_H5Aget_type(attr_id);
2282 if (dtype_id < 0) {
2283 threadsafe_H5Aclose(attr_id);
2284 XLAL_ERROR_NULL(XLAL_EIO, "Could not read type of attribute `%s'", key);
2285 }
2286
2287 /* must be compound data type ... */
2288 if (threadsafe_H5Tget_class(dtype_id) != H5T_COMPOUND) {
2289 threadsafe_H5Tclose(dtype_id);
2290 threadsafe_H5Aclose(attr_id);
2291 XLAL_ERROR_NULL(XLAL_ETYPE, "Incorrect data type for attribute `%s'", key);
2292 }
2293
2294 /* must have 2 members ... */
2295 if (threadsafe_H5Tget_nmembers(dtype_id) != 2) {
2296 threadsafe_H5Tclose(dtype_id);
2297 threadsafe_H5Aclose(attr_id);
2298 XLAL_ERROR_NULL(XLAL_ETYPE, "Incorrect data type for attribute `%s'", key);
2299 }
2300
2301 /* both members must be integer type ... */
2302 if (threadsafe_H5Tget_member_class(dtype_id, 0) != H5T_INTEGER) {
2303 threadsafe_H5Tclose(dtype_id);
2304 threadsafe_H5Aclose(attr_id);
2305 XLAL_ERROR_NULL(XLAL_ETYPE, "Incorrect data type for attribute `%s'", key);
2306 }
2307 if (threadsafe_H5Tget_member_class(dtype_id, 1) != H5T_INTEGER) {
2308 threadsafe_H5Tclose(dtype_id);
2309 threadsafe_H5Aclose(attr_id);
2310 XLAL_ERROR_NULL(XLAL_ETYPE, "Incorrect data type for attribute `%s'", key);
2311 }
2312
2313 /* FIXME: should also check member sizes? */
2314
2315 /* first member name must be "gpsSeconds" ... */
2316 s = threadsafe_H5Tget_member_name(dtype_id, 0);
2317 if (strcmp(s, "gpsSeconds") != 0) {
2318 free(s);
2319 threadsafe_H5Tclose(dtype_id);
2320 threadsafe_H5Aclose(attr_id);
2321 XLAL_ERROR_NULL(XLAL_ETYPE, "Incorrect data type for attribute `%s'", key);
2322 }
2323 free(s);
2324
2325 /* second member name must be "gpsNanoSeconds" ... */
2326 s = threadsafe_H5Tget_member_name(dtype_id, 1);
2327 if (strcmp(s, "gpsNanoSeconds") != 0) {
2328 free(s);
2329 threadsafe_H5Tclose(dtype_id);
2330 threadsafe_H5Aclose(attr_id);
2331 XLAL_ERROR_NULL(XLAL_ETYPE, "Incorrect data type for attribute `%s'", key);
2332 }
2333 free(s);
2334
2335 threadsafe_H5Tclose(dtype_id);
2336
2337 memtype_id = XLALH5TypeNativeLIGOTimeGPS();
2338 if (memtype_id < 0) {
2339 threadsafe_H5Aclose(attr_id);
2340 XLAL_ERROR_NULL(XLAL_EIO, "Could not get native type of attribute `%s'", key);
2341 }
2342
2343 if (threadsafe_H5Aread(attr_id, memtype_id, value) < 0) {
2344 threadsafe_H5Tclose(memtype_id);
2345 threadsafe_H5Aclose(attr_id);
2346 XLAL_ERROR_NULL(XLAL_EIO, "Could not read data from attribute `%s'", key);
2347 }
2348
2349 threadsafe_H5Tclose(memtype_id);
2350 threadsafe_H5Aclose(attr_id);
2351 return value;
2352#endif
2353}
2354
2355/**
2356 * @brief Gets the length of a 1D enum array attribute in a ::LALH5File or
2357 * ::LALH5Dataset
2358 * @details
2359 * This routine queries the length of a 1D enum array with name @p key in a
2360 * HDF5 object associated with the ::LALH5File or ::LALH5Dataset @p object.
2361 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to be queried.
2362 * @param key Pointer to a string with the name of the attribute to query.
2363 * @returns Length of the 1D enum array.
2364 * @retval -1 Failure.
2365 */
2366size_t XLALH5AttributeQueryEnumArray1DLength(const LALH5Generic UNUSED object, const char UNUSED *key)
2367{
2368#ifndef HAVE_HDF5
2369 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2370#else
2371 hsize_t dims[] = {-1};
2372 hid_t obj_id;
2373 hid_t attr_id;
2374 hid_t dtype_id;
2375
2376 obj_id = object.generic->object_id;
2377 if (obj_id < 0)
2379
2380 attr_id = threadsafe_H5Aopen(obj_id, key, H5P_DEFAULT);
2381 if (attr_id < 0)
2382 XLAL_ERROR(XLAL_EIO, "Could not read attribute `%s'", key);
2383
2384 dtype_id = threadsafe_H5Aget_type(attr_id);
2385 if (dtype_id < 0) {
2386 threadsafe_H5Aclose(attr_id);
2387 XLAL_ERROR(XLAL_EIO, "Could not read type of attribute `%s'", key);
2388 }
2389
2390 /* must be array data type ... */
2391 if (threadsafe_H5Tget_class(dtype_id) != H5T_ARRAY) {
2392 threadsafe_H5Tclose(dtype_id);
2393 threadsafe_H5Aclose(attr_id);
2394 XLAL_ERROR(XLAL_ETYPE, "Incorrect data type for attribute `%s'", key);
2395 }
2396
2397 /* must be a 1d array data type ... */
2398 if (threadsafe_H5Tget_array_ndims(dtype_id) != 1) {
2399 threadsafe_H5Tclose(dtype_id);
2400 threadsafe_H5Aclose(attr_id);
2401 XLAL_ERROR(XLAL_ETYPE, "Incorrect data type for attribute `%s'", key);
2402 }
2403
2404 if (threadsafe_H5Tget_array_dims2(dtype_id, dims) < 0) {
2405 threadsafe_H5Tclose(dtype_id);
2406 threadsafe_H5Aclose(attr_id);
2407 XLAL_ERROR(XLAL_ETYPE, "Could not get array length of attribute `%s'", key);
2408 }
2409
2410 threadsafe_H5Tclose(dtype_id);
2411 threadsafe_H5Aclose(attr_id);
2412 return dims[0];
2413#endif
2414}
2415
2416/**
2417 * @brief Gets the values in a 1D enum array attribute in a ::LALH5File or
2418 * ::LALH5Dataset
2419 * @details
2420 * This routine reads the values of a 1D enum array with name @p key in a
2421 * HDF5 object associated with the ::LALH5File or ::LALH5Dataset @p object
2422 * into the array @p value.
2423 *
2424 * @attention
2425 * This routine does not allocate memory for @p value. The calling
2426 * routine must ensure that the memory addressed by the pointer @p value
2427 * is sufficient to hold the value in the attribute.
2428 * The routine XLALH5AttributeQueryEnumArray1DLength() will yield the
2429 * length that this array must have.
2430 *
2431 * @param value Pointer to an array where then enum values will be stored.
2432 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to be queried.
2433 * @param key Pointer to a string with the name of the attribute to query.
2434 * @retval 0 Success.
2435 * @retval -1 Failure.
2436 */
2437int XLALH5AttributeQueryEnumArray1DValue(int UNUSED value[], const LALH5Generic UNUSED object, const char UNUSED *key)
2438{
2439#ifndef HAVE_HDF5
2440 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2441#else
2442 hid_t obj_id;
2443 hid_t attr_id;
2444 hid_t dtype_id;
2445
2446 obj_id = object.generic->object_id;
2447 if (obj_id < 0)
2449
2450 attr_id = threadsafe_H5Aopen(obj_id, key, H5P_DEFAULT);
2451 if (attr_id < 0)
2452 XLAL_ERROR(XLAL_EIO, "Could not read attribute `%s'", key);
2453
2454 dtype_id = threadsafe_H5Aget_type(attr_id);
2455 if (dtype_id < 0) {
2456 threadsafe_H5Aclose(attr_id);
2457 XLAL_ERROR(XLAL_EIO, "Could not read type of attribute `%s'", key);
2458 }
2459
2460 /* must be array data type ... */
2461 if (threadsafe_H5Tget_class(dtype_id) != H5T_ARRAY) {
2462 threadsafe_H5Tclose(dtype_id);
2463 threadsafe_H5Aclose(attr_id);
2464 XLAL_ERROR(XLAL_ETYPE, "Incorrect data type for attribute `%s'", key);
2465 }
2466
2467 /* must be a 1d array data type ... */
2468 if (threadsafe_H5Tget_array_ndims(dtype_id) != 1) {
2469 threadsafe_H5Tclose(dtype_id);
2470 threadsafe_H5Aclose(attr_id);
2471 XLAL_ERROR(XLAL_ETYPE, "Incorrect data type for attribute `%s'", key);
2472 }
2473
2474 if (threadsafe_H5Aread(attr_id, dtype_id, value) < 0) {
2475 threadsafe_H5Tclose(dtype_id);
2476 threadsafe_H5Aclose(attr_id);
2477 XLAL_ERROR(XLAL_ETYPE, "Could not read data from attribute `%s'", key);
2478 }
2479
2480 threadsafe_H5Tclose(dtype_id);
2481 threadsafe_H5Aclose(attr_id);
2482 return 0;
2483#endif
2484}
2485
2486/**
2487 * @brief Gets the number of constants in an enum type associated with an
2488 * attribute in a ::LALH5File or ::LALH5Dataset
2489 * @details
2490 * This routine queries the number constants in an enum type associated
2491 * with the attribute with name @p key in a
2492 * HDF5 object associated with the ::LALH5File or ::LALH5Dataset @p object.
2493 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to be queried.
2494 * @param key Pointer to a string with the name of the attribute to query.
2495 * @returns Number of constants in enum type.
2496 * @retval -1 Failure.
2497 */
2498size_t XLALH5AttributeQueryNEnum(const LALH5Generic UNUSED object, const char UNUSED *key)
2499{
2500#ifndef HAVE_HDF5
2501 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2502#else
2503 hid_t obj_id;
2504 hid_t attr_id;
2505 hid_t dtype_id;
2506 H5T_class_t dtype_class;
2507 int nenum;
2508
2509 obj_id = object.generic->object_id;
2510 if (obj_id < 0)
2512
2513 attr_id = threadsafe_H5Aopen(obj_id, key, H5P_DEFAULT);
2514 if (attr_id < 0)
2515 XLAL_ERROR(XLAL_EIO, "Could not read attribute `%s'", key);
2516
2517 dtype_id = threadsafe_H5Aget_type(attr_id);
2518 if (dtype_id < 0) {
2519 threadsafe_H5Aclose(attr_id);
2520 XLAL_ERROR(XLAL_EIO, "Could not read type of attribute `%s'", key);
2521 }
2522
2523 dtype_class = threadsafe_H5Tget_class(dtype_id);
2524 if (dtype_class == H5T_ARRAY) {
2525 /* get base data type */
2526 hid_t super_id;
2527 super_id = threadsafe_H5Tget_super(dtype_id);
2528 threadsafe_H5Tclose(dtype_id);
2529 dtype_id = super_id;
2530 dtype_class = threadsafe_H5Tget_class(dtype_id);
2531 }
2532 if (dtype_class == H5T_NO_CLASS) {
2533 threadsafe_H5Tclose(dtype_id);
2534 threadsafe_H5Aclose(attr_id);
2535 XLAL_ERROR(XLAL_EIO, "Could not read type class of attribute `%s'", key);
2536 }
2537 if (dtype_class != H5T_ENUM) {
2538 threadsafe_H5Tclose(dtype_id);
2539 threadsafe_H5Aclose(attr_id);
2540 XLAL_ERROR(XLAL_EIO, "Attribute `%s' is not an enum type", key);
2541 }
2542
2543 nenum = threadsafe_H5Tget_nmembers(dtype_id);
2544 if (nenum < 0) {
2545 threadsafe_H5Tclose(dtype_id);
2546 threadsafe_H5Aclose(attr_id);
2547 XLAL_ERROR(XLAL_EIO, "Could not read number of enum constants of attribute `%s'", key);
2548 }
2549
2550 threadsafe_H5Tclose(dtype_id);
2551 threadsafe_H5Aclose(attr_id);
2552 return nenum;
2553#endif
2554}
2555
2556/**
2557 * @brief Gets the name of a constants in an enum type associated with an
2558 * attribute in a ::LALH5File or ::LALH5Dataset
2559 * @details
2560 * This routine queries the name of a constant in an enum type associated
2561 * with the attribute with name @p key in a
2562 * HDF5 object associated with the ::LALH5File or ::LALH5Dataset @p object.
2563 * The index @p pos identifies which constant's name is returned.
2564 * The result is written into the buffer pointed to by @p name, the size
2565 * of which is @p size bytes. If @p name is NULL, no data is copied but
2566 * the routine returns the length of the string. Therefore, this routine
2567 * can be called once to determine the amount of memory required, the
2568 * memory can be allocated, and then it can be called a second time to
2569 * read the string. If the parameter @p size is less than or equal to
2570 * the string length then only $p size-1 bytes of the string are copied
2571 * to the buffer @p name.
2572 * @note The return value is the length of the string, not including the
2573 * terminating NUL character; thus the buffer @p name should be allocated
2574 * to be one byte larger.
2575 * @param name Pointer to a buffer into which the string will be written.
2576 * @param size Size in bytes of the buffer into which the string will be
2577 * written.
2578 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to be queried.
2579 * @param key Pointer to a string with the name of the attribute to query.
2580 * @param pos The index identifying which enum constant.
2581 * @returns The number of bytes that would be written to @p name had @p size
2582 * been sufficiently large excluding the terminating NUL byte.
2583 * @retval -1 Failure.
2584 */
2585int XLALH5AttributeQueryEnumName(char UNUSED *name, size_t UNUSED size, const LALH5Generic UNUSED object, const char UNUSED *key, int UNUSED pos)
2586{
2587#ifndef HAVE_HDF5
2588 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2589#else
2590 hid_t obj_id;
2591 hid_t attr_id;
2592 hid_t dtype_id;
2593 H5T_class_t dtype_class;
2594 int nenum;
2595 int n;
2596 char *s;
2597
2598 obj_id = object.generic->object_id;
2599 if (obj_id < 0)
2601
2602 attr_id = threadsafe_H5Aopen(obj_id, key, H5P_DEFAULT);
2603 if (attr_id < 0)
2604 XLAL_ERROR(XLAL_EIO, "Could not read attribute `%s'", key);
2605
2606 dtype_id = threadsafe_H5Aget_type(attr_id);
2607 if (dtype_id < 0) {
2608 threadsafe_H5Aclose(attr_id);
2609 XLAL_ERROR(XLAL_EIO, "Could not read type of attribute `%s'", key);
2610 }
2611
2612 dtype_class = threadsafe_H5Tget_class(dtype_id);
2613 if (dtype_class == H5T_ARRAY) {
2614 /* get base data type */
2615 hid_t super_id;
2616 super_id = threadsafe_H5Tget_super(dtype_id);
2617 threadsafe_H5Tclose(dtype_id);
2618 dtype_id = super_id;
2619 dtype_class = threadsafe_H5Tget_class(dtype_id);
2620 }
2621 if (dtype_class == H5T_NO_CLASS) {
2622 threadsafe_H5Tclose(dtype_id);
2623 threadsafe_H5Aclose(attr_id);
2624 XLAL_ERROR(XLAL_EIO, "Could not read type class of attribute `%s'", key);
2625 }
2626 if (dtype_class != H5T_ENUM) {
2627 threadsafe_H5Tclose(dtype_id);
2628 threadsafe_H5Aclose(attr_id);
2629 XLAL_ERROR(XLAL_EIO, "Attribute `%s' is not an enum type", key);
2630 }
2631
2632 nenum = threadsafe_H5Tget_nmembers(dtype_id);
2633 if (nenum < 0) {
2634 threadsafe_H5Tclose(dtype_id);
2635 threadsafe_H5Aclose(attr_id);
2636 XLAL_ERROR(XLAL_EIO, "Could not read number of enum constants of attribute `%s'", key);
2637 }
2638 if (pos >= nenum) {
2639 threadsafe_H5Tclose(dtype_id);
2640 threadsafe_H5Aclose(attr_id);
2641 XLAL_ERROR(XLAL_EINVAL, "Requested enum constant of attribute `%s' does not exist", key);
2642 }
2643
2644 s = threadsafe_H5Tget_member_name(dtype_id, pos);
2645 if (s == NULL) {
2646 threadsafe_H5Tclose(dtype_id);
2647 threadsafe_H5Aclose(attr_id);
2648 XLAL_ERROR(XLAL_EIO, "Could not read enum constant name of attribute `%s'", key);
2649 }
2650
2651 n = snprintf(name, name == NULL ? 0 : size, "%s", s);
2652
2653 free(s);
2654 threadsafe_H5Tclose(dtype_id);
2655 threadsafe_H5Aclose(attr_id);
2656 return n;
2657#endif
2658}
2659
2660/**
2661 * @brief Gets the value of a constants in an enum type associated with an
2662 * attribute in a ::LALH5File or ::LALH5Dataset
2663 * @details
2664 * This routine queries the value of a constant in an enum type associated
2665 * with the attribute with name @p key in a
2666 * HDF5 object associated with the ::LALH5File or ::LALH5Dataset @p object.
2667 * The index @p pos identifies which constant's name is returned.
2668 * @param object Pointer to a ::LALH5File or ::LALH5Dataset to be queried.
2669 * @param key Pointer to a string with the name of the attribute to query.
2670 * @param pos The index identifying which enum constant.
2671 * @returns The value of the enum constant.
2672 * @retval -1 Failure. Note that -1 might also be a valid enum constant!
2673 */
2674int XLALH5AttributeQueryEnumValue(const LALH5Generic UNUSED object, const char UNUSED *key, int UNUSED pos)
2675{
2676#ifndef HAVE_HDF5
2677 XLAL_ERROR_VAL(INT_MAX, XLAL_EFAILED, "HDF5 support not implemented");
2678#else
2679 hid_t obj_id;
2680 hid_t attr_id;
2681 hid_t dtype_id;
2682 H5T_class_t dtype_class;
2683 int nenum;
2684 int val;
2685
2686 obj_id = object.generic->object_id;
2687 if (obj_id < 0)
2689
2690 attr_id = threadsafe_H5Aopen(obj_id, key, H5P_DEFAULT);
2691 if (attr_id < 0)
2692 XLAL_ERROR(XLAL_EIO, "Could not read attribute `%s'", key);
2693
2694 dtype_id = threadsafe_H5Aget_type(attr_id);
2695 if (dtype_id < 0) {
2696 threadsafe_H5Aclose(attr_id);
2697 XLAL_ERROR(XLAL_EIO, "Could not read type of attribute `%s'", key);
2698 }
2699
2700 dtype_class = threadsafe_H5Tget_class(dtype_id);
2701 if (dtype_class == H5T_ARRAY) {
2702 /* get base data type */
2703 hid_t super_id;
2704 super_id = threadsafe_H5Tget_super(dtype_id);
2705 threadsafe_H5Tclose(dtype_id);
2706 dtype_id = super_id;
2707 dtype_class = threadsafe_H5Tget_class(dtype_id);
2708 }
2709 if (dtype_class == H5T_NO_CLASS) {
2710 threadsafe_H5Tclose(dtype_id);
2711 threadsafe_H5Aclose(attr_id);
2712 XLAL_ERROR(XLAL_EIO, "Could not read type class of attribute `%s'", key);
2713 }
2714 if (dtype_class != H5T_ENUM) {
2715 threadsafe_H5Tclose(dtype_id);
2716 threadsafe_H5Aclose(attr_id);
2717 XLAL_ERROR(XLAL_EIO, "Attribute `%s' is not an enum type", key);
2718 }
2719
2720 nenum = threadsafe_H5Tget_nmembers(dtype_id);
2721 if (nenum < 0) {
2722 threadsafe_H5Tclose(dtype_id);
2723 threadsafe_H5Aclose(attr_id);
2724 XLAL_ERROR(XLAL_EIO, "Could not read number of enum constants of attribute `%s'", key);
2725 }
2726 if (pos >= nenum) {
2727 threadsafe_H5Tclose(dtype_id);
2728 threadsafe_H5Aclose(attr_id);
2729 XLAL_ERROR(XLAL_EINVAL, "Requested enum constant of attribute `%s' does not exist", key);
2730 }
2731
2732 if (threadsafe_H5Tget_member_value(dtype_id, pos, &val) < 0)
2733 {
2734 threadsafe_H5Tclose(dtype_id);
2735 threadsafe_H5Aclose(attr_id);
2736 XLAL_ERROR(XLAL_EIO, "Could not read enum constant value of attribute `%s'", key);
2737 }
2738
2739 threadsafe_H5Tclose(dtype_id);
2740 threadsafe_H5Aclose(attr_id);
2741 return val;
2742#endif
2743}
2744
2745/** @} */
2746
2747/**
2748 * @name File Attribute Routines
2749 *
2750 * @deprecated
2751 * Use the general @ref attribute_routines "Attribute Routines"
2752 * instead.
2753 *
2754 * @{
2755 */
2756
2757/**
2758 * @brief DEPRECATED: Adds a scalar attribute to a ::LALH5File
2759 * @details
2760 * This routine adds a scalar-valued attribute with name @p key
2761 * and value given by the memory addressed by @p value to a
2762 * HDF5 file associated with the ::LALH5File @p file.
2763 * The data type of the scalar value is given by the \c LALTYPECODE
2764 * @p dtype.
2765 *
2766 * @deprecated
2767 * Use XLALH5AttributeAddScalar() instead.
2768 *
2769 * @param file Pointer to a ::LALH5File to which the attribute will be added.
2770 * @param key Pointer to a string with the name of the new attribute.
2771 * @param value Pointer to the value of the scalar attribute to be added.
2772 * @param dtype \c LALTYPECODE value specifying the data type of the attribute.
2773 * @retval 0 Success.
2774 * @retval -1 Failure.
2775 */
2776int XLALH5FileAddScalarAttribute(LALH5File UNUSED *file, const char UNUSED *key, const void UNUSED *value, LALTYPECODE UNUSED dtype)
2777{
2778#ifndef HAVE_HDF5
2779 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2780#else
2781 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeAddScalar");
2782 if (XLALH5AttributeAddScalar((LALH5Generic)file, key, value, dtype) < 0)
2784 return 0;
2785#endif
2786}
2787
2788/**
2789 * @brief DEPRECATED: Gets attribute names from a ::LALH5File
2790 * @details
2791 * This routine returns the names of all attributes from a HDF5 Dataset
2792 *
2793 * @deprecated
2794 * Use XLALH5AttributeQueryN() and XLALH5AttributeQueryName() instead.
2795 *
2796 * @param names Pointer a list of strings to be returned to the user. Memory
2797 * should be freed by the caller.
2798 * @param file Pointer to a ::LALH5File from which the attributes will be added.
2799 * @param N Pointer to a UINT4 where the number of datasets will be recorded
2800 * @retval 0 Success.
2801 * @retval -1 Failure.
2802 */
2803int XLALH5FileGetAttributeNames(LALH5File UNUSED *file, char UNUSED *** names, UINT4 UNUSED *N)
2804{
2805#ifndef HAVE_HDF5
2806 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2807#else
2808 int na;
2809 int ns;
2810 int i;
2811 hid_t aid;
2812
2813 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeQueryN() and XLALH5AttributeQueryName");
2814 if (file == NULL)
2816 if (names == NULL)
2818
2819 na = threadsafe_H5Aget_num_attrs(file->file_id);
2820 char ** namelist = (char**) XLALMalloc(na * sizeof(*names));
2821
2822 for (i = 0; i <na; i++) {
2823 aid = threadsafe_H5Aopen_idx(file->file_id, (unsigned int)i);
2824 ns = threadsafe_H5Aget_name(aid, 0, NULL) + 1;
2825 namelist[i] = (char*) XLALMalloc(ns * sizeof(namelist[i]));
2826 threadsafe_H5Aget_name(aid, ns, namelist[i]);
2827 threadsafe_H5Aclose(aid);
2828 }
2829
2830 *N=na;
2831 *names = namelist;
2832 return(XLAL_SUCCESS);
2833#endif
2834}
2835
2836
2837/**
2838 * @brief DEPRECATED: Adds a string attribute to a ::LALH5File
2839 * @details
2840 * This routine adds a NUL-terminated variable-length string @p value
2841 * attribute with name @p key to a HDF5 file associated with the
2842 * ::LALH5File @p file.
2843 *
2844 * @deprecated
2845 * Use XLALH5AttributeAddString() instead.
2846 *
2847 * @param file Pointer to a ::LALH5File to which the attribute will be added.
2848 * @param key Pointer to a string with the name of the new attribute.
2849 * @param value Pointer to a string with the value of the new attribute.
2850 * @retval 0 Success.
2851 * @retval -1 Failure.
2852 */
2853int XLALH5FileAddStringAttribute(LALH5File UNUSED *file, const char UNUSED *key, const char UNUSED *value)
2854{
2855#ifndef HAVE_HDF5
2856 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2857#else
2858 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeAddString");
2859 if (XLALH5AttributeAddString((LALH5Generic)file, key, value) < 0)
2861 return 0;
2862#endif
2863}
2864
2865/**
2866 * @brief DEPRECATED: Adds a LIGOTimeGPS attribute to a ::LALH5File
2867 * @details
2868 * This routine adds a LIGOTimeGPS @p value attribute with name @p key to a
2869 * HDF5 file associated with the ::LALH5File @p file.
2870 *
2871 * @deprecated
2872 * Use XLALH5AttributeAddLIGOTimeGPS() instead.
2873 *
2874 * @param file Pointer to a ::LALH5File to which the attribute will be added.
2875 * @param key Pointer to a string with the name of the new attribute.
2876 * @param value Pointer to a LIGOTimeGPS structure with the value of the new
2877 * attribute.
2878 * @retval 0 Success.
2879 * @retval -1 Failure.
2880 */
2881int XLALH5FileAddLIGOTimeGPSAttribute(LALH5File UNUSED *file, const char UNUSED *key, const LIGOTimeGPS UNUSED *value)
2882{
2883#ifndef HAVE_HDF5
2884 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2885#else
2886 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeAddLIGOTimeGPS");
2887 if (XLALH5AttributeAddLIGOTimeGPS((LALH5Generic)file, key, value) < 0)
2889 return 0;
2890#endif
2891}
2892
2893/**
2894 * @brief DEPRECATED: Gets the datatype of an attribute in a ::LALH5File
2895 * @details
2896 * This routine queries the datatype of a scalar attribute with
2897 * name @p key in a HDF5 file associated with the ::LALH5File @p file.
2898 *
2899 * @deprecated
2900 * Use XLALH5AttributeQueryScalarType() instead.
2901 *
2902 * @param file Pointer to a ::LALH5File to be queried.
2903 * @param key Pointer to a string with the name of the attribute to query.
2904 * @returns \c LALTYPECODE value of the datatype of the scalar attribute.
2905 * @retval -1 Failure.
2906 */
2908{
2909#ifndef HAVE_HDF5
2910 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2911#else
2912 LALTYPECODE dtype;
2913
2914 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeQueryScalarType");
2916 if ((int)(dtype) < 0)
2918
2919 return dtype;
2920#endif
2921}
2922
2923/**
2924 * @brief DEPRECATED: Gets the value of a scalar attribute in a ::LALH5File
2925 * @details
2926 * This routine queries the value of a scalar attribute with
2927 * name @p key in a HDF5 file associated with the ::LALH5File @p file.
2928 * The value is stored in memory pointed to by the pointer @p value.
2929 *
2930 * @attention
2931 * This routine does not allocate memory for @p value. The calling
2932 * routine must ensure that the memory addressed by the pointer @p value
2933 * is sufficient to hold the value in the attribute.
2934 *
2935 * @deprecated
2936 * Use XLALH5AttributeQueryScalarValue() instead.
2937 *
2938 * @param value Pointer to memory in which the value will be stored.
2939 * @param file Pointer to a ::LALH5File to be queried.
2940 * @param key Pointer to a string with the name of the attribute to query.
2941 * @retval 0 Success.
2942 * @retval -1 Failure.
2943 */
2944int XLALH5FileQueryScalarAttributeValue(void UNUSED *value, LALH5File UNUSED *file, const char UNUSED *key)
2945{
2946#ifndef HAVE_HDF5
2947 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2948#else
2949 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeQueryScalarValue");
2952 return 0;
2953#endif
2954}
2955
2956/**
2957 * @brief DEPRECATED: Gets the value of a string attribute in a ::LALH5File
2958 * @details
2959 * This routine queries the value of a string attribute with
2960 * name @p key in a HDF5 file associated with the ::LALH5File @p file.
2961 * The result is written into the buffer pointed to by @p value, the size
2962 * of which is @p size bytes. If @p value is NULL, no data is copied but
2963 * the routine returns the length of the string. Therefore, this routine
2964 * can be called once to determine the amount of memory required, the
2965 * memory can be allocated, and then it can be called a second time to
2966 * read the string. If the parameter @p size is less than or equal to
2967 * the string length then only $p size-1 bytes of the string are copied
2968 * to the buffer @p value.
2969 * @note The return value is the length of the string, not including the
2970 * terminating NUL character; thus the buffer @p value should be allocated
2971 * to be one byte larger.
2972 *
2973 * @deprecated
2974 * Use XLALH5AttributeQueryStringValue() instead.
2975 *
2976 * @param value Pointer to a buffer into which the string will be written.
2977 * @param size Size in bytes of the buffer into which the string will be
2978 * written.
2979 * @param file Pointer to a ::LALH5File to be queried.
2980 * @param key Pointer to a string with the name of the attribute to query.
2981 * @returns The number of bytes that would be written to @p value had @p size
2982 * been sufficiently large excluding the terminating NUL byte.
2983 * @retval -1 Failure.
2984 */
2985int XLALH5FileQueryStringAttributeValue(char UNUSED *value, size_t UNUSED size, LALH5File UNUSED *file, const char UNUSED *key)
2986{
2987#ifndef HAVE_HDF5
2988 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
2989#else
2990 int n;
2991
2992 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeQueryStringValue");
2993 n = XLALH5AttributeQueryStringValue(value, size, (LALH5Generic)file, key);
2994 if (n < 0)
2996
2997 return n;
2998#endif
2999}
3000
3001/**
3002 * @brief DEPRECATED: Gets the value of a LIGOTimeGPS attribute in a ::LALH5File
3003 * @details
3004 * This routine queries the value of a LIGOTimeGPS attribute with
3005 * name @p key in a HDF5 file associated with the ::LALH5File @p file.
3006 * The value is stored in memory pointed to by the pointer @p value.
3007 *
3008 * @deprecated
3009 * Use XLALH5AttributeQueryLIGOTimeGPSValue() instead.
3010 *
3011 * @param value Pointer to a LIGOTimeGPS structure in which the attribute
3012 * value will be stored.
3013 * @param file Pointer to a ::LALH5File to be queried.
3014 * @param key Pointer to a string with the name of the attribute to query.
3015 * @returns Pointer to the LIGOTimeGPS structure passed to this routine.
3016 * @retval NULL Failure.
3017 */
3018LIGOTimeGPS * XLALH5FileQueryLIGOTimeGPSAttributeValue(LIGOTimeGPS UNUSED *value, LALH5File UNUSED *file, const char UNUSED *key)
3019{
3020#ifndef HAVE_HDF5
3021 XLAL_ERROR_NULL(XLAL_EFAILED, "HDF5 support not implemented");
3022#else
3023 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeQueryLIGOTimeGPSValue");
3024 if (XLALH5AttributeQueryLIGOTimeGPSValue(value, (LALH5Generic)file, key) == NULL)
3026 return value;
3027#endif
3028}
3029
3030/** @} */
3031
3032/**
3033 * @name Dataset Attribute Routines
3034 *
3035 * @deprecated
3036 * Use the general @ref attribute_routines "Attribute Routines"
3037 * instead.
3038 *
3039 * @{
3040 */
3041
3042/**
3043 * @brief DEPRECATED: Adds a scalar attribute to a ::LALH5Dataset
3044 * @details
3045 * This routine adds a scalar-valued attribute with name @p key
3046 * and value given by the memory addressed by @p value to a
3047 * HDF5 dataset associated with the ::LALH5Dataset @p dset.
3048 * The data type of the scalar value is given by the \c LALTYPECODE
3049 * @p dtype.
3050 *
3051 * @deprecated
3052 * Use XLALH5AttributeAddScalar() instead.
3053 *
3054 * @param dset Pointer to a ::LALH5Dataset to which the attribute will be added.
3055 * @param key Pointer to a string with the name of the new attribute.
3056 * @param value Pointer to the value of the scalar attribute to be added.
3057 * @param dtype \c LALTYPECODE value specifying the data type of the attribute.
3058 * @retval 0 Success.
3059 * @retval -1 Failure.
3060 */
3061int XLALH5DatasetAddScalarAttribute(LALH5Dataset UNUSED *dset, const char UNUSED *key, const void UNUSED *value, LALTYPECODE UNUSED dtype)
3062{
3063#ifndef HAVE_HDF5
3064 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3065#else
3066 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeAddScalar");
3067 if (XLALH5AttributeAddScalar((LALH5Generic)dset, key, value, dtype) < 0)
3069 return 0;
3070#endif
3071}
3072
3073/**
3074 * @brief DEPRECATED: Adds a string attribute to a ::LALH5Dataset
3075 * @details
3076 * This routine adds a NUL-terminated variable-length string @p value
3077 * attribute with name @p key to a HDF5 dataset associated with the
3078 * ::LALH5Dataset @p dset.
3079 *
3080 * @deprecated
3081 * Use XLALH5AttributeAddString() instead.
3082 *
3083 * @param dset Pointer to a ::LALH5Dataset to which the attribute will be added.
3084 * @param key Pointer to a string with the name of the new attribute.
3085 * @param value Pointer to a string with the value of the new attribute.
3086 * @retval 0 Success.
3087 * @retval -1 Failure.
3088 */
3089int XLALH5DatasetAddStringAttribute(LALH5Dataset UNUSED *dset, const char UNUSED *key, const char UNUSED *value)
3090{
3091#ifndef HAVE_HDF5
3092 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3093#else
3094 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeAddString");
3095 if (XLALH5AttributeAddString((LALH5Generic)dset, key, value) < 0)
3097 return 0;
3098#endif
3099}
3100
3101/**
3102 * @brief DEPRECATED: Adds a LIGOTimeGPS attribute to a ::LALH5Dataset
3103 * @details
3104 * This routine adds a LIGOTimeGPS @p value attribute with name @p key to a
3105 * HDF5 dataset associated with the ::LALH5Dataset @p dset.
3106 *
3107 * @deprecated
3108 * Use XLALH5AttributeAddLIGOTimeGPS() instead.
3109 *
3110 * @param dset Pointer to a ::LALH5Dataset to which the attribute will be added.
3111 * @param key Pointer to a string with the name of the new attribute.
3112 * @param value Pointer to a LIGOTimeGPS structure with the value of the new
3113 * attribute.
3114 * @retval 0 Success.
3115 * @retval -1 Failure.
3116 */
3117int XLALH5DatasetAddLIGOTimeGPSAttribute(LALH5Dataset UNUSED *dset, const char UNUSED *key, const LIGOTimeGPS UNUSED *value)
3118{
3119#ifndef HAVE_HDF5
3120 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3121#else
3122 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeAddLIGOTimeGPS");
3123 if (XLALH5AttributeAddLIGOTimeGPS((LALH5Generic)dset, key, value) < 0)
3125 return 0;
3126#endif
3127}
3128
3129/**
3130 * @brief DEPRECATED: Gets the datatype of an attribute in a ::LALH5Dataset
3131 * @details
3132 * This routine queries the datatype of a scalar attribute with
3133 * name @p key in a HDF5 dataset associated with the ::LALH5Dataset @p dset.
3134 *
3135 * @deprecated
3136 * Use XLALH5AttributeQueryScalarType() instead.
3137 *
3138 * @param dset Pointer to a ::LALH5Dataset to be queried.
3139 * @param key Pointer to a string with the name of the attribute to query.
3140 * @returns \c LALTYPECODE value of the datatype of the scalar attribute.
3141 * @retval -1 Failure.
3142 */
3144{
3145#ifndef HAVE_HDF5
3146 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3147#else
3148 LALTYPECODE dtype;
3149
3150 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeQueryScalarType");
3151 dtype = XLALH5AttributeQueryScalarType((LALH5Generic)dset, key);
3152 if ((int)(dtype) < 0)
3154
3155 return dtype;
3156#endif
3157}
3158
3159/**
3160 * @brief DEPRECATED: Gets the value of a scalar attribute in a ::LALH5Dataset
3161 * @details
3162 * This routine queries the value of a scalar attribute with
3163 * name @p key in a HDF5 dataset associated with the ::LALH5Dataset @p dset.
3164 * The value is stored in memory pointed to by the pointer @p value.
3165 *
3166 * @attention
3167 * This routine does not allocate memory for @p value. The calling
3168 * routine must ensure that the memory addressed by the pointer @p value
3169 * is sufficient to hold the value in the attribute.
3170 *
3171 * @deprecated
3172 * Use XLALH5AttributeQueryScalarValue() instead.
3173 *
3174 * @param value Pointer to memory in which the value will be stored.
3175 * @param dset Pointer to a ::LALH5Dataset to be queried.
3176 * @param key Pointer to a string with the name of the attribute to query.
3177 * @retval 0 Success.
3178 * @retval -1 Failure.
3179 */
3180int XLALH5DatasetQueryScalarAttributeValue(void UNUSED *value, LALH5Dataset UNUSED *dset, const char UNUSED *key)
3181{
3182#ifndef HAVE_HDF5
3183 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3184#else
3185 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeQueryScalarValue");
3186 if (XLALH5AttributeQueryScalarValue(value, (LALH5Generic)dset, key) < 0)
3188 return 0;
3189#endif
3190}
3191
3192/**
3193 * @brief DEPRECATED: Gets the value of a string attribute in a ::LALH5Dataset
3194 * @details
3195 * This routine queries the value of a string attribute with
3196 * name @p key in a HDF5 dataset associated with the ::LALH5Dataset @p dset.
3197 * The result is written into the buffer pointed to by @p value, the size
3198 * of which is @p size bytes. If @p value is NULL, no data is copied but
3199 * the routine returns the length of the string. Therefore, this routine
3200 * can be called once to determine the amount of memory required, the
3201 * memory can be allocated, and then it can be called a second time to
3202 * read the string. If the parameter @p size is less than or equal to
3203 * the string length then only $p size-1 bytes of the string are copied
3204 * to the buffer @p value.
3205 * @note The return value is the length of the string, not including the
3206 * terminating NUL character; thus the buffer @p value should be allocated
3207 * to be one byte larger.
3208 *
3209 * @deprecated
3210 * Use XLALH5AttributeQueryStringValue() instead.
3211 *
3212 * @param value Pointer to a buffer into which the string will be written.
3213 * @param size Size in bytes of the buffer into which the string will be
3214 * written.
3215 * @param dset Pointer to a ::LALH5Dataset to be queried.
3216 * @param key Pointer to a string with the name of the attribute to query.
3217 * @returns The number of bytes that would be written to @p value had @p size
3218 * been sufficiently large excluding the terminating NUL byte.
3219 * @retval NULL Failure.
3220 */
3221int XLALH5DatasetQueryStringAttributeValue(char UNUSED *value, size_t UNUSED size, LALH5Dataset UNUSED *dset, const char UNUSED *key)
3222{
3223#ifndef HAVE_HDF5
3224 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3225#else
3226 int n;
3227
3228 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeQueryStringValue");
3229 n = XLALH5AttributeQueryStringValue(value, size, (LALH5Generic)dset, key);
3230 if (n < 0)
3232
3233 return n;
3234#endif
3235}
3236
3237/**
3238 * @brief DEPRECATED: Gets the value of a LIGOTimeGPS attribute in a ::LALH5Dataset
3239 * @details
3240 * This routine queries the value of a LIGOTimeGPS attribute with
3241 * name @p key in a HDF5 dataset associated with the ::LALH5Dataset @p dset.
3242 * The value is stored in memory pointed to by the pointer @p value.
3243 *
3244 * @deprecated
3245 * Use XLALH5AttributeQueryLIGOTimeGPSValue() instead.
3246 *
3247 * @param value Pointer to a LIGOTimeGPS structure in which the attribute
3248 * value will be stored.
3249 * @param dset Pointer to a ::LALH5Dataset to be queried.
3250 * @param key Pointer to a string with the name of the attribute to query.
3251 * @returns Pointer to the LIGOTimeGPS structure passed to this routine.
3252 * @retval NULL Failure.
3253 */
3254LIGOTimeGPS * XLALH5DatasetQueryLIGOTimeGPSAttributeValue(LIGOTimeGPS UNUSED *value, LALH5Dataset UNUSED *dset, const char UNUSED *key)
3255{
3256#ifndef HAVE_HDF5
3257 XLAL_ERROR_NULL(XLAL_EFAILED, "HDF5 support not implemented");
3258#else
3259 XLAL_PRINT_DEPRECATION_WARNING("XLALH5AttributeQueryLIGOTimeGPSValue");
3260 if (XLALH5AttributeQueryLIGOTimeGPSValue(value, (LALH5Generic)dset, key) == NULL)
3262 return value;
3263#endif
3264}
3265
3266/** @} */
3267
3268/** @} */
3269
3270/**
3271 * @addtogroup H5Table_group
3272 * @brief Routines for reading/writing tables in HDF5 files.
3273 * @details
3274 * These routines are basic routines for reading and writing
3275 * tables in HDF5 files.
3276 * @{
3277 */
3278
3279/**
3280 * @brief Allocates a ::LALH5Dataset dataset to hold a table.
3281 * @details
3282 * This routine creates a dataset with name @p name within an HDF5
3283 * file associated with the ::LALH5File @p file structure and allocates
3284 * a ::LALH5Dataset structure associated with the dataset. The type
3285 * of data to be stored are table data comprised of rows of size
3286 * @p rowsz; each row having @p ncols columns with names @p cols, types @p
3287 * types, and offsets @p offsets.
3288
3289 * with the ::LALH5Dataset @p dset and stores the data in the buffer @p data.
3290 * This buffer should be sufficiently large to hold the requested rows
3291 * of the dataset, which is comprised of a number of rows each of size
3292 * @p rowsz. Each row is comprised of a number of columns
3293 * which are named in the comma-separated list in string @p cols.
3294 * The offsets of the columns and the sizes of the columns in each row
3295 * of data is provided by the arrays @p offsets and @p colsz respectively.
3296 *
3297 * The following example shows how to create a dataset named @a particles
3298 * in which particle data can be stored.
3299 * @code
3300 * #include <stddef.h>
3301 * #include <lal/LALStdlib.h>
3302 * #include <lal/LALH5FileIO.h>
3303 *
3304 * struct body {REAL8 x; REAL8 y; REAL8 z; REAL8 vx; REAL8 vy; REAL8 vz;};
3305 * size_t ncols = 6;
3306 * size_t types[6] = {LAL_D_TYPE_CODE, LAL_D_TYPE_CODE, LAL_D_TYPE_CODE, LAL_D_TYPE_CODE, LAL_D_TYPE_CODE, LAL_D_TYPE_CODE};
3307 * size_t offsets[6] = {offsetof(struct body, x), offsetof(struct body, y), offsetof(struct body, z), offsetof(struct body, vx), offsetof(struct body, vy), offsetof(struct body, vz)};
3308 * size_t rowsz = sizeof(*data);
3309 * LALH5File *file = XLALH5FileOpen("example.h5", "w");
3310 * LALH5Dataset *dset = XLALH5TableAlloc(file, "particles", ncols, cols, types, offsets, rowsz);
3311 * @endcode
3312 *
3313 * @param file Pointer to a ::LALH5File in which to create the dataset.
3314 * @param name Pointer to a string with the name of the dataset to create (also
3315 * the table name).
3316 * @param ncols Number of columns in each row.
3317 * @param cols Pointer to an array of strings giving the column names.
3318 * @param types Pointer to an array of \c LALTYPECODE values specifying the data
3319 * type of each column.
3320 * @param offsets Pointer to an array of offsets for each column.
3321 * @param rowsz Size of each row of data.
3322 * @returns A pointer to a ::LALH5Dataset structure associated with the specified
3323 * dataset within a HDF5 file.
3324 * @retval NULL An error occurred creating the dataset.
3325 */
3326LALH5Dataset * XLALH5TableAlloc(LALH5File UNUSED *file, const char UNUSED *name, size_t UNUSED ncols, const char UNUSED **cols, const LALTYPECODE UNUSED *types, const size_t UNUSED *offsets, size_t UNUSED rowsz)
3327{
3328#ifndef HAVE_HDF5
3329 XLAL_ERROR_NULL(XLAL_EFAILED, "HDF5 support not implemented");
3330#else
3331 const size_t chunk_size = 32;
3332 hid_t dtype_id[ncols];
3333 hid_t tdtype_id;
3334 size_t col;
3335 size_t namelen;
3336 herr_t status;
3337 LALH5Dataset *dset;
3338
3339 if (file == NULL || cols == NULL || types == NULL || offsets == NULL)
3341
3342 if (file->mode != LAL_H5_FILE_MODE_WRITE)
3343 XLAL_ERROR_NULL(XLAL_EINVAL, "Attempting to write to a read-only HDF5 file");
3344
3345 /* map the LAL types to HDF5 types */
3346 for (col = 0; col < ncols; ++col) {
3347 dtype_id[col] = XLALH5TypeFromLALType(types[col]);
3348 if (dtype_id[col] < 0)
3350 }
3351
3352 /* make empty table */
3353 /* note: table title and dataset name are the same */
3354 status = threadsafe_H5TBmake_table(name, file->file_id, name, ncols, 0, rowsz, cols, offsets, dtype_id, chunk_size, NULL, 0, NULL);
3355 for (col = 0; col < ncols; ++col)
3356 threadsafe_H5Tclose(dtype_id[col]);
3357
3358 if (status < 0)
3360
3361 /* now read dataset from file to return */
3362
3363 namelen = strlen(name);
3364 dset = LALCalloc(1, sizeof(*dset) + namelen + 1); /* use flexible array member to record name */
3365 if (!dset)
3367
3368 dset->dataset_id = threadsafe_H5Dopen2(file->file_id, name, H5P_DEFAULT);
3369 if (dset->dataset_id < 0) {
3370 LALFree(dset);
3371 XLAL_ERROR_NULL(XLAL_EIO, "Could not read dataset `%s'", name);
3372 }
3373
3374 dset->space_id = threadsafe_H5Dget_space(dset->dataset_id);
3375 if (dset->space_id < 0) {
3376 LALFree(dset);
3377 XLAL_ERROR_NULL(XLAL_EIO, "Could not read dataspace of dataset `%s'", name);
3378 }
3379
3380 tdtype_id = threadsafe_H5Dget_type(dset->dataset_id);
3381 if (tdtype_id < 0) {
3382 threadsafe_H5Sclose(dset->space_id);
3383 LALFree(dset);
3384 XLAL_ERROR_NULL(XLAL_EIO, "Could not read datatype of dataset `%s'", name);
3385 }
3386
3387 /* convert type to native type */
3388 dset->dtype_id = threadsafe_H5Tget_native_type(tdtype_id, H5T_DIR_ASCEND);
3389 threadsafe_H5Tclose(tdtype_id);
3390 if (dset->dtype_id < 0) {
3391 threadsafe_H5Sclose(dset->space_id);
3392 LALFree(dset);
3393 XLAL_ERROR_NULL(XLAL_EIO, "Could not get native type for dataset `%s'", name);
3394 }
3395
3396 /* record name of dataset and parent id */
3397 snprintf(dset->name, namelen + 1, "%s", name);
3398 dset->parent_id = file->file_id;
3399 return dset;
3400#endif
3401}
3402
3403/**
3404 * @brief Appends rows of data to a ::LALH5Dataset dataset holding a table.
3405 * @details
3406 * This routine appends @p nrows rows of data each having size @p rowsz
3407 * to a HDF5 table dataset associated with the ::LALH5Dataset structure
3408 * @p dset. The data is contained in @p data and the offsets and sizes
3409 * of each column are given by the arrays @p offsets and @p colsz.
3410 *
3411 * The following example shows how to append rows to a dataset named
3412 * @a particles in which particle data is stored.
3413 * @code
3414 * #include <stddef.h>
3415 * #include <lal/LALStdlib.h>
3416 * #include <lal/LALH5FileIO.h>
3417 *
3418 * struct body {REAL8 x; REAL8 y; REAL8 z; REAL8 vx; REAL8 vy; REAL8 vz;} data[] = {
3419 * { .x = +0.83, .y = -0.13, .z = -0.24, .vx = +0.60, .vy = -0.79, .vz = -0.98 },
3420 * { .x = -0.59, .y = -0.12, .z = -0.60, .vx = +0.38, .vy = +0.61, .vz = -0.75 },
3421 * { .x = -0.48, .y = -0.78, .z = +0.83, .vx = -0.58, .vy = -0.09, .vz = +0.44 },
3422 * { .x = +0.99, .y = -0.13, .z = -0.48, .vx = +0.44, .vy = +0.06, .vz = -0.58 },
3423 * { .x = -0.26, .y = +0.92, .z = -0.98, .vx = -0.75, .vy = +0.45, .vz = +0.30 },
3424 * { .x = +0.88, .y = -0.50, .z = +0.53, .vx = -0.82, .vy = +0.50, .vz = -0.36 },
3425 * { .x = -0.20, .y = +0.55, .z = +0.85, .vx = -0.87, .vy = +0.41, .vz = +0.38 },
3426 * { .x = +0.48, .y = -0.09, .z = +0.29, .vx = -0.76, .vy = +0.27, .vz = -0.38 },
3427 * { .x = +0.11, .y = -0.13, .z = -0.02, .vx = +0.69, .vy = +0.64, .vz = +0.06 },
3428 * { .x = -0.85, .y = +0.08, .z = -0.25, .vx = -0.20, .vy = -0.69, .vz = +0.77 }
3429 * };
3430 * size_t nrows = sizeof(data)/sizeof(*data);
3431 * size_t ncols = 6;
3432 * size_t types[6] = {LAL_D_TYPE_CODE, LAL_D_TYPE_CODE, LAL_D_TYPE_CODE, LAL_D_TYPE_CODE, LAL_D_TYPE_CODE, LAL_D_TYPE_CODE};
3433 * size_t offsets[6] = {offsetof(struct body, x), offsetof(struct body, y), offsetof(struct body, z), offsetof(struct body, vx), offsetof(struct body, vy), offsetof(struct body, vz)};
3434 * size_t colsz[6] = {sizeof(data->x), sizeof(data->y), sizeof(data->z), sizeof(data->vx), sizeof(data->vy), sizeof(data->vz)};
3435 * size_t rowsz = sizeof(*data);
3436 * LALH5File *file = XLALH5FileOpen("example.h5", "w");
3437 * LALH5Dataset *dset = XLALH5TableAlloc(file, "particles", ncols, cols, types, offsets, rowsz);
3438 * XLALH5TableAppend(dset, offsets, colsz, nrows, rowsz, data);
3439 * @endcode
3440 *
3441 * @param dset Pointer to a ::LALH5Dataset containing the table into which the
3442 * rows will be appended.
3443 * @param offsets Pointer to an array of offsets for each column.
3444 * @param colsz Pointer to an array of sizes of each column.
3445 * @param nrows Number of rows of data that will be appended.
3446 * @param rowsz Size of each row of data.
3447 * @param data Pointer to a memory in which contains the data to be appended.
3448 * @retval 0 Success.
3449 * @retval -1 Failure.
3450 */
3451int XLALH5TableAppend(LALH5Dataset UNUSED *dset, const size_t UNUSED *offsets, const size_t UNUSED *colsz, size_t UNUSED nrows, size_t UNUSED rowsz, const void UNUSED *data)
3452{
3453#ifndef HAVE_HDF5
3454 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3455#else
3456 if (dset == NULL || offsets == NULL || colsz == NULL)
3458
3459 if (threadsafe_H5TBappend_records(dset->parent_id, dset->name, nrows, rowsz, offsets, colsz, data) < 0)
3461
3462 return 0;
3463#endif
3464}
3465
3466/**
3467 * @brief Reads table data from a ::LALH5Dataset
3468 * @details
3469 * This routine reads the table data from a HDF5 dataset associated with the
3470 * ::LALH5Dataset @p dset and stores the data in the buffer @p data.
3471 * This buffer should be sufficiently large to hold the entire contents
3472 * of the dataset, which is comprised of a number of rows each of size
3473 * @p rowsz. The number of rows can be determined with the routine
3474 * XLALH5TableQueryNRows(). Each row is comprised of a number of columns,
3475 * which can be determined with the routine XLALH5TableQueryNColumns().
3476 * The offsets of the columns and the sizes of the columns in each row
3477 * of data is provided by the arrays @p offsets and @p colsz respectively.
3478 *
3479 * The following example shows how to read the data from a table
3480 * named @a particles.
3481 * @code
3482 * #include <stddef.h>
3483 * #include <lal/LALStdlib.h>
3484 * #include <lal/LALH5FileIO.h>
3485 *
3486 * struct body {REAL8 x; REAL8 y; REAL8 z; REAL8 vx; REAL8 vy; REAL8 vz;} *data;
3487 * size_t offsets[] = {offsetof(struct body, x), offsetof(struct body, y), offsetof(struct body, z), offsetof(struct body, vx), offsetof(struct body, vy), offsetof(struct body, vz)};
3488 * size_t colsz[] = {sizeof(data->x), sizeof(data->y), sizeof(data->z), sizeof(data->vx), sizeof(data->vy), sizeof(data->vz)};
3489 * size_t rowsz = sizeof(*data);
3490 * LALH5File *file = XLALH5FileOpen("example.h5", "r");
3491 * LALH5Dataset *dset = XLALH5DatasetRead(file, "particles");
3492 * size_t nrows = XLALH5TableQueryNRows(dset);
3493 * data = LALMalloc(nrows * rowsz);
3494 * XLALH5TableRead(data, dset, offsets, colsz, rowsz);
3495 * @endcode
3496 *
3497 * @param data Pointer to a memory in which to store the data.
3498 * @param dset Pointer to a ::LALH5Dataset from which to extract the data.
3499 * @param offsets Pointer to an array of offsets for each column.
3500 * @param colsz Pointer to an array of sizes of each column.
3501 * @param rowsz Size of each row of data.
3502 * @retval 0 Success.
3503 * @retval -1 Failure.
3504 */
3505int XLALH5TableRead(void UNUSED *data, const LALH5Dataset UNUSED *dset, const size_t UNUSED *offsets, const size_t UNUSED *colsz, size_t UNUSED rowsz)
3506{
3507#ifndef HAVE_HDF5
3508 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3509#else
3510 if (data == NULL || dset == NULL || offsets == NULL || colsz == NULL)
3512
3513 if (threadsafe_H5TBread_table(dset->parent_id, dset->name, rowsz, offsets, colsz, data) < 0)
3515
3516 return 0;
3517#endif
3518}
3519
3520/**
3521 * @brief Reads certain rows of table data from a ::LALH5Dataset
3522 * @details
3523 * This routine reads certain rows of table data from a HDF5 dataset associated
3524 * with the ::LALH5Dataset @p dset and stores the data in the buffer @p data.
3525 * This buffer should be sufficiently large to hold the requested @p nrows rows
3526 * of the dataset, starting with row @p row0 (the first row is row 0), which is
3527 * comprised of a number of rows each of size @p rowsz. Each row is comprised
3528 * of a number of columns, which can be determined with the routine
3529 * XLALH5TableQueryNColumns(). The offsets of the columns and the sizes of the
3530 * columns in each row of data is provided by the arrays @p offsets and
3531 * @p colsz respectively.
3532 *
3533 * The following example shows how to read rows 2 to 5 inclusive
3534 * (where the first row is row 0) of data from a table named
3535 * @a particles.
3536 * @code
3537 * #include <stddef.h>
3538 * #include <lal/LALStdlib.h>
3539 * #include <lal/LALH5FileIO.h>
3540 *
3541 * struct body {REAL8 x; REAL8 y; REAL8 z; REAL8 vx; REAL8 vy; REAL8 vz;} data[4];
3542 * size_t offsets[] = {offsetof(struct body, x), offsetof(struct body, y), offsetof(struct body, z), offsetof(struct body, vx), offsetof(struct body, vy), offsetof(struct body, vz)};
3543 * size_t colsz[] = {sizeof(data->x), sizeof(data->y), sizeof(data->z), sizeof(data->vx), sizeof(data->vy), sizeof(data->vz)};
3544 * size_t rowsz = sizeof(*data);
3545 * size_t row0 = 2;
3546 * size_t nrows = sizeof(data)/sizeof(*data);
3547 * LALH5File *file = XLALH5FileOpen("example.h5", "r");
3548 * LALH5Dataset *dset = XLALH5DatasetRead(file, "particles");
3549 * XLALH5TableReadRows(data, dset, offsets, colsz, row0, nrows, rowsz);
3550 * @endcode
3551 *
3552 * @param data Pointer to a memory in which to store the data.
3553 * @param dset Pointer to a ::LALH5Dataset from which to extract the data.
3554 * @param offsets Pointer to an array of offsets for each column.
3555 * @param colsz Pointer to an array of sizes of each column.
3556 * @param row0 The first row to read.
3557 * @param nrows The Number of rows to read.
3558 * @param rowsz Size of each row of data.
3559 * @retval 0 Success.
3560 * @retval -1 Failure.
3561 */
3562int XLALH5TableReadRows(void UNUSED *data, const LALH5Dataset UNUSED *dset, const size_t UNUSED *offsets, const size_t UNUSED *colsz, size_t UNUSED row0, size_t UNUSED nrows, size_t UNUSED rowsz)
3563{
3564#ifndef HAVE_HDF5
3565 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3566#else
3567 if (data == NULL || dset == NULL || offsets == NULL || colsz == NULL)
3569
3570 if (threadsafe_H5TBread_records(dset->parent_id, dset->name, row0, nrows, rowsz, offsets, colsz, data) < 0)
3572
3573 return 0;
3574#endif
3575}
3576
3577/**
3578 * @brief Reads certain columns of table data from a ::LALH5Dataset
3579 * @details
3580 * This routine reads certain columns of table data from a HDF5 dataset associated
3581 * with the ::LALH5Dataset @p dset and stores the data in the buffer @p data.
3582 * This buffer should be sufficiently large to hold the requested rows
3583 * of the dataset, which is comprised of a number of rows each of size
3584 * @p rowsz. Each row is comprised of a number of columns
3585 * which are named in the comma-separated list in string @p cols.
3586 * The offsets of the columns and the sizes of the columns in each row
3587 * of data is provided by the arrays @p offsets and @p colsz respectively.
3588 *
3589 * The following example shows how to read rows 2 to 5 inclusive
3590 * (where the first row is row 0) of certain columns of data from a table named
3591 * @a particles.
3592 * @code
3593 * #include <stddef.h>
3594 * #include <lal/LALStdlib.h>
3595 * #include <lal/LALH5FileIO.h>
3596 *
3597 * struct position {REAL8 x; REAL8 y; REAL8 z;} data[4];
3598 * const char *cols = "x,y,z";
3599 * size_t offsets[] = {offsetof(struct position, x), offsetof(struct position, y), offsetof(struct position, z)};
3600 * size_t colsz[] = {sizeof(data->x), sizeof(data->y), sizeof(data->z)};
3601 * size_t rowsz = sizeof(*data);
3602 * size_t row0 = 2;
3603 * size_t nrows = sizeof(data)/sizeof(*data);
3604 * LALH5File *file = XLALH5FileOpen("example.h5", "r");
3605 * LALH5Dataset *dset = XLALH5DatasetRead(file, "particles");
3606 * XLALH5TableReadColumns(data, dset, cols, offsets, colsz, row0, nrows, rowsz);
3607 * @endcode
3608 *
3609 * @param data Pointer to a memory in which to store the data.
3610 * @param dset Pointer to a ::LALH5Dataset from which to extract the data.
3611 * @param cols Pointer to an string listing the column names separated by commas.
3612 * @param offsets Pointer to an array of offsets for each column.
3613 * @param colsz Pointer to an array of sizes of each column.
3614 * @param row0 The first row to read.
3615 * @param nrows The Number of rows to read.
3616 * @param rowsz Size of each row of data.
3617 * @retval 0 Success.
3618 * @retval -1 Failure.
3619 */
3620int XLALH5TableReadColumns(void UNUSED *data, const LALH5Dataset UNUSED *dset, const char UNUSED *cols, const size_t UNUSED *offsets, const size_t UNUSED *colsz, size_t UNUSED row0, size_t UNUSED nrows, size_t UNUSED rowsz)
3621{
3622#ifndef HAVE_HDF5
3623 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3624#else
3625 if (data == NULL || dset == NULL || offsets == NULL || colsz == NULL)
3627
3628 if (threadsafe_H5TBread_fields_name(dset->parent_id, dset->name, cols, row0, nrows, rowsz, offsets, colsz, data) < 0)
3630
3631 return 0;
3632#endif
3633}
3634
3635/**
3636 * @brief Gets the number of rows in a ::LALH5Dataset containing table data.
3637 * @param dset Pointer to a ::LALH5Dataset containing table data to be queried.
3638 * @returns The number of rows of table data in the HDF5 dataset associated
3639 * with the specified ::LALH5Dataset.
3640 * @retval (size_t)(-1) Failure.
3641 */
3642size_t XLALH5TableQueryNRows(const LALH5Dataset UNUSED *dset)
3643{
3644#ifndef HAVE_HDF5
3645 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3646#else
3647 hsize_t nrows;
3648
3649 if (dset == NULL)
3651
3652 if (threadsafe_H5TBget_table_info(dset->parent_id, dset->name, NULL, &nrows) < 0)
3654
3655 return nrows;
3656#endif
3657}
3658
3659/**
3660 * @brief Gets the number of columns in a ::LALH5Dataset containing table data.
3661 * @param dset Pointer to a ::LALH5Dataset containing table data to be queried.
3662 * @returns The number of columns of table data in the HDF5 dataset associated
3663 * with the specified ::LALH5Dataset.
3664 * @retval (size_t)(-1) Failure.
3665 */
3666size_t XLALH5TableQueryNColumns(const LALH5Dataset UNUSED *dset)
3667{
3668#ifndef HAVE_HDF5
3669 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3670#else
3671 hsize_t ncols;
3672
3673 if (dset == NULL)
3675
3676 if (threadsafe_H5TBget_table_info(dset->parent_id, dset->name, &ncols, NULL) < 0)
3678
3679 return ncols;
3680#endif
3681}
3682
3683/**
3684 * @brief Gets the number of bytes in a row in a ::LALH5Dataset containing table
3685 * data.
3686 * @param dset Pointer to a ::LALH5Dataset containing table data to be queried.
3687 * @returns The number of bytes of a row of data in the HDF5 dataset associated
3688 * with the specified ::LALH5Dataset.
3689 * @retval (size_t)(-1) Failure.
3690 */
3691size_t XLALH5TableQueryRowSize(const LALH5Dataset UNUSED *dset)
3692{
3693#ifndef HAVE_HDF5
3694 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3695#else
3696 size_t rowsz;
3697
3698 if (dset == NULL)
3700
3701 if (threadsafe_H5TBget_field_info(dset->parent_id, dset->name, NULL, NULL, NULL, &rowsz) < 0)
3703
3704 return rowsz;
3705#endif
3706}
3707
3708/**
3709 * @brief Gets the name of a column in a ::LALH5Dataset containing table
3710 * data.
3711 * @details
3712 * This routines gets the name of a column of data in a ::LALH5Dataset
3713 * @p dset that contains table data.
3714 * The index @p pos identifies which column's name is returned.
3715 * The result is written into the buffer pointed to by @p name, the size
3716 * of which is @p size bytes. If @p name is NULL, no data is copied but
3717 * the routine returns the length of the string. Therefore, this routine
3718 * can be called once to determine the amount of memory required, the
3719 * memory can be allocated, and then it can be called a second time to
3720 * read the string. If the parameter @p size is less than or equal to
3721 * the string length then only $p size-1 bytes of the string are copied
3722 * to the buffer @p name.
3723 * @note The return value is the length of the string, not including the
3724 * terminating NUL character; thus the buffer @p name should be allocated
3725 * to be one byte larger.
3726 * @param name Pointer to a buffer into which the string will be written.
3727 * @param size Size in bytes of the buffer into which the string will be
3728 * written.
3729 * @param dset Pointer to a ::LALH5Dataset containing table data to be
3730 * queried.
3731 * @param pos The index identifying which column of the table.
3732 * @retval 0 Success.
3733 * @retval -1 Failure.
3734 */
3735int XLALH5TableQueryColumnName(char UNUSED *name, size_t UNUSED size, const LALH5Dataset UNUSED *dset, int UNUSED pos)
3736{
3737#ifndef HAVE_HDF5
3738 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3739#else
3740 int ncols;
3741 char *col;
3742 int n;
3743
3744 if (dset == NULL)
3746
3747 ncols = threadsafe_H5Tget_nmembers(dset->dtype_id);
3748 if (ncols < 0)
3749 XLAL_ERROR(XLAL_EIO, "Could not read type members");
3750
3751 if (ncols <= pos)
3752 XLAL_ERROR(XLAL_EINVAL, "Requested column does not exist");
3753
3754 col = threadsafe_H5Tget_member_name(dset->dtype_id, pos);
3755 if (col == NULL)
3756 XLAL_ERROR(XLAL_EIO, "Could not read column name");
3757
3758 n = snprintf(name, name == NULL ? 0 : size, "%s", col);
3759 free(col);
3760 return n;
3761#endif
3762}
3763
3764/**
3765 * @brief Gets the size in bytes of a column in a ::LALH5Dataset containing table
3766 * data.
3767 * @param dset Pointer to a ::LALH5Dataset containing table data to be
3768 * queried.
3769 * @param pos The index identifying which column of the table.
3770 * @returns The size in bytes of the specified column entry in the HDF5 dataset
3771 * associated with the specified ::LALH5Dataset.
3772 * @retval -1 Failure.
3773 */
3774size_t XLALH5TableQueryColumnSize(const LALH5Dataset UNUSED *dset, int UNUSED pos)
3775{
3776#ifndef HAVE_HDF5
3777 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3778#else
3779 hid_t member_type_id;
3780 hid_t native_member_type_id;
3781 int ncols;
3782 size_t size;
3783
3784 if (dset == NULL)
3786
3787 ncols = threadsafe_H5Tget_nmembers(dset->dtype_id);
3788 if (ncols < 0)
3789 XLAL_ERROR(XLAL_EIO, "Could not read type members");
3790
3791 if (ncols <= pos)
3792 XLAL_ERROR(XLAL_EINVAL, "Requested column does not exist");
3793
3794 member_type_id = threadsafe_H5Tget_member_type(dset->dtype_id, pos);
3795 if (member_type_id < 0)
3796 XLAL_ERROR(XLAL_EIO, "Could not read column type");
3797
3798 native_member_type_id = threadsafe_H5Tget_native_type(member_type_id, H5T_DIR_DEFAULT);
3799 if (native_member_type_id < 0) {
3800 threadsafe_H5Tclose(member_type_id);
3801 XLAL_ERROR(XLAL_EIO, "Could not read column native type");
3802 }
3803
3804 size = threadsafe_H5Tget_size(native_member_type_id);
3805 if (size == 0) {
3806 threadsafe_H5Tclose(native_member_type_id);
3807 threadsafe_H5Tclose(member_type_id);
3808 XLAL_ERROR(XLAL_EIO, "Could not read column size");
3809 }
3810
3811 threadsafe_H5Tclose(native_member_type_id);
3812 threadsafe_H5Tclose(member_type_id);
3813
3814 return size;
3815#endif
3816}
3817
3818/**
3819 * @brief Gets the type of data stored in a column in a ::LALH5Dataset
3820 * containing table data.
3821 * @param dset Pointer to a ::LALH5Dataset containing table data to be
3822 * queried.
3823 * @param pos The index identifying which column of the table.
3824 * @returns The \c LALTYPECODE of the datatype of the specified column entry in
3825 * the HDF5 dataset associated with the specified ::LALH5Dataset.
3826 * @retval -1 Failure.
3827 */
3828LALTYPECODE XLALH5TableQueryColumnType(const LALH5Dataset UNUSED *dset, int UNUSED pos)
3829{
3830#ifndef HAVE_HDF5
3831 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3832#else
3833 hid_t member_type_id;
3834 int ncols;
3835 LALTYPECODE type;
3836
3837 if (dset == NULL)
3839
3840 ncols = threadsafe_H5Tget_nmembers(dset->dtype_id);
3841 if (ncols < 0)
3842 XLAL_ERROR(XLAL_EIO, "Could not read type members");
3843
3844 if (ncols <= pos)
3845 XLAL_ERROR(XLAL_EINVAL, "Requested column does not exist");
3846
3847 member_type_id = threadsafe_H5Tget_member_type(dset->dtype_id, pos);
3848 if (member_type_id < 0)
3849 XLAL_ERROR(XLAL_EIO, "Could not read column type");
3850
3851 type = XLALTypeFromH5Type(member_type_id);
3852 threadsafe_H5Tclose(member_type_id);
3853
3854 if ((int)type < 0)
3856 return type;
3857#endif
3858}
3859
3860/**
3861 * @brief Gets the offset of the data in a column in a ::LALH5Dataset
3862 * containing table data.
3863 * @param dset Pointer to a ::LALH5Dataset containing table data to be
3864 * queried.
3865 * @param pos The index identifying which column of the table.
3866 * @returns The offset of the specified column data in a row of data
3867 * in the HDF5 dataset associated with the specified ::LALH5Dataset.
3868 * @retval (size_t)(-1) Failure.
3869 */
3870size_t XLALH5TableQueryColumnOffset(const LALH5Dataset UNUSED *dset, int UNUSED pos)
3871{
3872#ifndef HAVE_HDF5
3873 XLAL_ERROR(XLAL_EFAILED, "HDF5 support not implemented");
3874#else
3875 int ncols;
3876 size_t offset;
3877
3878 if (dset == NULL)
3880
3881 ncols = threadsafe_H5Tget_nmembers(dset->dtype_id);
3882 if (ncols < 0)
3883 XLAL_ERROR(XLAL_EIO, "Could not read type members");
3884
3885 if (ncols <= pos)
3886 XLAL_ERROR(XLAL_EINVAL, "Requested column does not exist");
3887
3888 /* H5Tget_member_offset fails iff H5Tget_member_class does */
3889 if (threadsafe_H5Tget_member_class(dset->dtype_id, pos) < 0)
3890 XLAL_ERROR(XLAL_EINVAL, "Could not read offset");
3891
3892 offset = threadsafe_H5Tget_member_offset(dset->dtype_id, pos);
3893 return offset;
3894#endif
3895}
3896
3897/** @} */
struct tagLALH5File LALH5File
Incomplete type for a HDF5 file.
Definition: H5FileIO.h:93
struct tagLALH5Dataset LALH5Dataset
Incomplete type for a HDF5 dataset.
Definition: H5FileIO.h:102
#define LALCalloc(m, n)
Definition: LALMalloc.h:94
#define LALFree(p)
Definition: LALMalloc.h:96
const char *const name
type name
Definition: UserInput.c:193
const char * names[]
Definition: WindowTest.c:34
LIGOTimeGPS * XLALH5AttributeQueryLIGOTimeGPSValue(LIGOTimeGPS UNUSED *value, const LALH5Generic UNUSED object, const char UNUSED *key)
Gets the value of a LIGOTimeGPS attribute in a LALH5File or LALH5Dataset.
void XLALH5FileClose(LALH5File UNUSED *file)
Closes a LALH5File.
LALTYPECODE XLALH5AttributeQueryScalarType(const LALH5Generic UNUSED object, const char UNUSED *key)
Gets the datatype of an attribute in a LALH5File or LALH5Dataset.
int XLALH5FileQueryGroupName(char UNUSED *name, size_t UNUSED size, const LALH5File UNUSED *file, int UNUSED pos)
Gets the name of a group contained in a LALH5File.
size_t XLALH5DatasetQueryNPoints(LALH5Dataset UNUSED *dset)
Gets the number of points in a LALH5Dataset.
void XLALH5DatasetFree(LALH5Dataset UNUSED *dset)
Frees a LALH5Dataset.
int XLALH5AttributeQueryName(char UNUSED *name, size_t UNUSED size, const LALH5Generic UNUSED object, int UNUSED pos)
Gets the name of an attribute associated with a LALH5File or LALH5Dataset.
LIGOTimeGPS * XLALH5FileQueryLIGOTimeGPSAttributeValue(LIGOTimeGPS UNUSED *value, LALH5File UNUSED *file, const char UNUSED *key)
DEPRECATED: Gets the value of a LIGOTimeGPS attribute in a LALH5File.
int XLALH5CheckGroupExists(LALH5File UNUSED *file, const char UNUSED *name)
DEPRECATED: Checks for existence of a Group in a LALH5File object LALH5File.
size_t XLALH5FileQueryNDatasets(const LALH5File UNUSED *file)
Gets the number of datasets contained in a LALH5File.
size_t XLALH5DatasetQueryNBytes(LALH5Dataset UNUSED *dset)
Gets the number of bytes in a LALH5Dataset.
int XLALH5DatasetCheckFixedLengthStringData(LALH5Dataset UNUSED *dset)
Checks if a LALH5Dataset contains fixed length string data.
int XLALH5AttributeAddString(LALH5Generic UNUSED object, const char UNUSED *key, const char UNUSED *value)
Adds a string attribute to a LALH5File or LALH5Dataset.
int XLALH5AttributeQueryEnumName(char UNUSED *name, size_t UNUSED size, const LALH5Generic UNUSED object, const char UNUSED *key, int UNUSED pos)
Gets the name of a constants in an enum type associated with an attribute in a LALH5File or LALH5Data...
size_t XLALH5AttributeQueryEnumArray1DLength(const LALH5Generic UNUSED object, const char UNUSED *key)
Gets the length of a 1D enum array attribute in a LALH5File or LALH5Dataset.
int XLALH5DatasetQueryScalarAttributeValue(void UNUSED *value, LALH5Dataset UNUSED *dset, const char UNUSED *key)
DEPRECATED: Gets the value of a scalar attribute in a LALH5Dataset.
LALH5File * XLALH5GroupOpen(LALH5File UNUSED *file, const char UNUSED *name)
Opens a group in a LALH5File.
LALH5Dataset * XLALH5DatasetAlloc(LALH5File UNUSED *file, const char UNUSED *name, LALTYPECODE UNUSED dtype, UINT4Vector UNUSED *dimLength)
Allocates a multi-dimensional LALH5Dataset.
int XLALH5FileQueryScalarAttributeValue(void UNUSED *value, LALH5File UNUSED *file, const char UNUSED *key)
DEPRECATED: Gets the value of a scalar attribute in a LALH5File.
int XLALH5AttributeQueryStringValue(char UNUSED *value, size_t UNUSED size, const LALH5Generic UNUSED object, const char UNUSED *key)
Gets the value of a string attribute in a LALH5File or LALH5Dataset.
int XLALH5AttributeAddLIGOTimeGPS(LALH5Generic UNUSED object, const char UNUSED *key, const LIGOTimeGPS UNUSED *value)
Adds a LIGOTimeGPS attribute to a LALH5File or LALH5Dataset.
LALTYPECODE XLALH5DatasetQueryScalarAttributeType(LALH5Dataset UNUSED *dset, const char UNUSED *key)
DEPRECATED: Gets the datatype of an attribute in a LALH5Dataset.
int XLALH5FileAddLIGOTimeGPSAttribute(LALH5File UNUSED *file, const char UNUSED *key, const LIGOTimeGPS UNUSED *value)
DEPRECATED: Adds a LIGOTimeGPS attribute to a LALH5File.
LIGOTimeGPS * XLALH5DatasetQueryLIGOTimeGPSAttributeValue(LIGOTimeGPS UNUSED *value, LALH5Dataset UNUSED *dset, const char UNUSED *key)
DEPRECATED: Gets the value of a LIGOTimeGPS attribute in a LALH5Dataset.
int XLALH5DatasetAddLIGOTimeGPSAttribute(LALH5Dataset UNUSED *dset, const char UNUSED *key, const LIGOTimeGPS UNUSED *value)
DEPRECATED: Adds a LIGOTimeGPS attribute to a LALH5Dataset.
int XLALH5AttributeAddEnumArray1D(LALH5Generic UNUSED object, const char UNUSED *enumnames[], const int UNUSED enumvals[], size_t UNUSED nenum, const char UNUSED *key, const int UNUSED value[], size_t UNUSED length)
Adds a 1d enum array attribute to a LALH5File or LALH5Dataset.
int XLALH5FileQueryDatasetName(char UNUSED *name, size_t UNUSED size, const LALH5File UNUSED *file, int UNUSED pos)
Gets the name of a dataset contained in a LALH5File.
LALTYPECODE XLALH5FileQueryScalarAttributeType(LALH5File UNUSED *file, const char UNUSED *key)
DEPRECATED: Gets the datatype of an attribute in a LALH5File.
int XLALH5DatasetCheckStringData(LALH5Dataset UNUSED *dset)
Checks if a LALH5Dataset contains variable length string data.
int XLALH5AttributeQueryEnumValue(const LALH5Generic UNUSED object, const char UNUSED *key, int UNUSED pos)
Gets the value of a constants in an enum type associated with an attribute in a LALH5File or LALH5Dat...
int XLALH5DatasetAddStringAttribute(LALH5Dataset UNUSED *dset, const char UNUSED *key, const char UNUSED *value)
DEPRECATED: Adds a string attribute to a LALH5Dataset.
LALTYPECODE XLALH5DatasetQueryType(LALH5Dataset UNUSED *dset)
Gets the type of data in a LALH5Dataset.
int XLALH5DatasetQueryStringAttributeValue(char UNUSED *value, size_t UNUSED size, LALH5Dataset UNUSED *dset, const char UNUSED *key)
DEPRECATED: Gets the value of a string attribute in a LALH5Dataset.
int XLALH5FileAddScalarAttribute(LALH5File UNUSED *file, const char UNUSED *key, const void UNUSED *value, LALTYPECODE UNUSED dtype)
DEPRECATED: Adds a scalar attribute to a LALH5File.
int XLALH5FileCheckDatasetExists(const LALH5File UNUSED *file, const char UNUSED *name)
Checks for existence of a dataset in a LALH5File.
int XLALH5AttributeAddScalar(LALH5Generic UNUSED object, const char UNUSED *key, const void UNUSED *value, LALTYPECODE UNUSED dtype)
Adds a scalar attribute to a LALH5File or LALH5Dataset.
LALH5Dataset * XLALH5DatasetAlloc1D(LALH5File UNUSED *file, const char UNUSED *name, LALTYPECODE UNUSED dtype, size_t UNUSED length)
Allocates a 1-dimensional LALH5Dataset.
int XLALH5FileGetDatasetNames(LALH5File UNUSED *file, char UNUSED ***names, UINT4 UNUSED *N)
DEPRECATED: Gets dataset names from a LALH5File.
LALH5File * XLALH5FileOpen(const char UNUSED *path, const char UNUSED *mode)
Opens a LALH5File.
int XLALH5FileAddStringAttribute(LALH5File UNUSED *file, const char UNUSED *key, const char UNUSED *value)
DEPRECATED: Adds a string attribute to a LALH5File.
size_t XLALH5AttributeQueryNEnum(const LALH5Generic UNUSED object, const char UNUSED *key)
Gets the number of constants in an enum type associated with an attribute in a LALH5File or LALH5Data...
size_t XLALH5AttributeCheckExists(const LALH5Generic UNUSED object, const char UNUSED *name)
Checks for existence of an attribute associated with a LALH5File or LALH5Dataset.
int XLALH5AttributeQueryScalarValue(void UNUSED *value, const LALH5Generic UNUSED object, const char UNUSED *key)
Gets the value of a scalar attribute in a LALH5File or LALH5Dataset.
int XLALH5FileGetAttributeNames(LALH5File UNUSED *file, char UNUSED ***names, UINT4 UNUSED *N)
DEPRECATED: Gets attribute names from a LALH5File.
LALH5Dataset * XLALH5DatasetRead(LALH5File UNUSED *file, const char UNUSED *name)
Reads a LALH5Dataset.
int XLALH5FileCheckGroupExists(const LALH5File UNUSED *file, const char UNUSED *name)
Checks for existence of a group in a LALH5File.
int XLALH5DatasetQueryData(void UNUSED *data, LALH5Dataset UNUSED *dset)
Gets the data contained in a LALH5Dataset.
int XLALH5DatasetWrite(LALH5Dataset UNUSED *dset, void UNUSED *data)
Writes data to a LALH5Dataset.
size_t XLALH5AttributeQueryN(const LALH5Generic UNUSED object)
Gets the number of attributes associated with a LALH5File or LALH5Dataset.
int XLALH5DatasetQueryNDim(LALH5Dataset UNUSED *dset)
Gets the number of dimensions of the dataspace in a LALH5Dataset.
int XLALH5FileQueryStringAttributeValue(char UNUSED *value, size_t UNUSED size, LALH5File UNUSED *file, const char UNUSED *key)
DEPRECATED: Gets the value of a string attribute in a LALH5File.
LALH5Dataset * XLALH5DatasetAllocStringData(LALH5File UNUSED *file, const char UNUSED *name, size_t UNUSED length)
Allocates a variable-length string LALH5Dataset.
int XLALH5DatasetAddScalarAttribute(LALH5Dataset UNUSED *dset, const char UNUSED *key, const void UNUSED *value, LALTYPECODE UNUSED dtype)
DEPRECATED: Adds a scalar attribute to a LALH5Dataset.
int XLALH5AttributeQueryEnumArray1DValue(int UNUSED value[], const LALH5Generic UNUSED object, const char UNUSED *key)
Gets the values in a 1D enum array attribute in a LALH5File or LALH5Dataset.
size_t XLALH5FileQueryNGroups(const LALH5File UNUSED *file)
Gets the number of groups contained in a LALH5File.
UINT4Vector * XLALH5DatasetQueryDims(LALH5Dataset UNUSED *dset)
Gets the dimensions of the dataspace in a LALH5Dataset.
int XLALH5TableRead(void UNUSED *data, const LALH5Dataset UNUSED *dset, const size_t UNUSED *offsets, const size_t UNUSED *colsz, size_t UNUSED rowsz)
Reads table data from a LALH5Dataset.
LALTYPECODE XLALH5TableQueryColumnType(const LALH5Dataset UNUSED *dset, int UNUSED pos)
Gets the type of data stored in a column in a LALH5Dataset containing table data.
int XLALH5TableReadColumns(void UNUSED *data, const LALH5Dataset UNUSED *dset, const char UNUSED *cols, const size_t UNUSED *offsets, const size_t UNUSED *colsz, size_t UNUSED row0, size_t UNUSED nrows, size_t UNUSED rowsz)
Reads certain columns of table data from a LALH5Dataset.
size_t XLALH5TableQueryRowSize(const LALH5Dataset UNUSED *dset)
Gets the number of bytes in a row in a LALH5Dataset containing table data.
size_t XLALH5TableQueryNColumns(const LALH5Dataset UNUSED *dset)
Gets the number of columns in a LALH5Dataset containing table data.
size_t XLALH5TableQueryNRows(const LALH5Dataset UNUSED *dset)
Gets the number of rows in a LALH5Dataset containing table data.
int XLALH5TableQueryColumnName(char UNUSED *name, size_t UNUSED size, const LALH5Dataset UNUSED *dset, int UNUSED pos)
Gets the name of a column in a LALH5Dataset containing table data.
int XLALH5TableAppend(LALH5Dataset UNUSED *dset, const size_t UNUSED *offsets, const size_t UNUSED *colsz, size_t UNUSED nrows, size_t UNUSED rowsz, const void UNUSED *data)
Appends rows of data to a LALH5Dataset dataset holding a table.
int XLALH5TableReadRows(void UNUSED *data, const LALH5Dataset UNUSED *dset, const size_t UNUSED *offsets, const size_t UNUSED *colsz, size_t UNUSED row0, size_t UNUSED nrows, size_t UNUSED rowsz)
Reads certain rows of table data from a LALH5Dataset.
size_t XLALH5TableQueryColumnSize(const LALH5Dataset UNUSED *dset, int UNUSED pos)
Gets the size in bytes of a column in a LALH5Dataset containing table data.
size_t XLALH5TableQueryColumnOffset(const LALH5Dataset UNUSED *dset, int UNUSED pos)
Gets the offset of the data in a column in a LALH5Dataset containing table data.
LALH5Dataset * XLALH5TableAlloc(LALH5File UNUSED *file, const char UNUSED *name, size_t UNUSED ncols, const char UNUSED **cols, const LALTYPECODE UNUSED *types, const size_t UNUSED *offsets, size_t UNUSED rowsz)
Allocates a LALH5Dataset dataset to hold a table.
LALTYPECODE
Type codes: use these type codes to identify a LAL atomic data type, see Headers LAL(Atomic)Datatypes...
Definition: LALDatatypes.h:49
uint32_t UINT4
Four-byte unsigned integer.
@ LAL_C_TYPE_CODE
COMPLEX8 type code (27)
Definition: LALDatatypes.h:60
@ LAL_CHAR_TYPE_CODE
CHAR type code (0)
Definition: LALDatatypes.h:50
@ LAL_U2_TYPE_CODE
UINT2 type code (33)
Definition: LALDatatypes.h:55
@ LAL_Z_TYPE_CODE
COMPLEX16 type code (28)
Definition: LALDatatypes.h:61
@ LAL_S_TYPE_CODE
REAL4 type code (18)
Definition: LALDatatypes.h:58
@ LAL_I2_TYPE_CODE
INT2 type code (1)
Definition: LALDatatypes.h:51
@ LAL_I8_TYPE_CODE
INT8 type code (3)
Definition: LALDatatypes.h:53
@ LAL_D_TYPE_CODE
REAL8 type code (19)
Definition: LALDatatypes.h:59
@ LAL_I4_TYPE_CODE
INT4 type code (2)
Definition: LALDatatypes.h:52
@ LAL_UCHAR_TYPE_CODE
UCHAR type code (32)
Definition: LALDatatypes.h:54
@ LAL_U8_TYPE_CODE
UINT8 type code (35)
Definition: LALDatatypes.h:57
@ LAL_U4_TYPE_CODE
UINT4 type code (34)
Definition: LALDatatypes.h:56
@ LAL_4_BYTE_TYPE_SIZE
Four byte size 010 = 2.
Definition: LALDatatypes.h:35
@ LAL_2_BYTE_TYPE_SIZE
Two byte size 01 = 1.
Definition: LALDatatypes.h:34
@ LAL_8_BYTE_TYPE_SIZE
Eight byte size 011 = 3.
Definition: LALDatatypes.h:36
@ LAL_16_BYTE_TYPE_SIZE
Sixteen byte size 0100 = 4.
Definition: LALDatatypes.h:37
@ LAL_1_BYTE_TYPE_SIZE
One byte size 00 = 0.
Definition: LALDatatypes.h:33
@ LAL_TYPE_SIZE_MASK
Type size mask 0111 = 7.
Definition: LALDatatypes.h:38
@ LAL_UNSGN_TYPE_FLAG
Unsigned (vs signed) type 0100000 = 32.
Definition: LALDatatypes.h:45
@ LAL_FLTPT_TYPE_FLAG
Floating-point (vs integer) type 01000 = 8.
Definition: LALDatatypes.h:43
@ LAL_CMPLX_TYPE_FLAG
Complex (vs real) type 010000 = 16.
Definition: LALDatatypes.h:44
#define XLALMalloc(n)
Definition: LALMalloc.h:44
#define XLALFree(p)
Definition: LALMalloc.h:47
size_t XLALStringCopy(char *dst, const char *src, size_t size)
Copy sources string src to destination string dst.
Definition: LALString.c:104
int XLALStringNCaseCompare(const char *s1, const char *s2, size_t n)
Compare the first N characters of two strings, ignoring case and without using locale-dependent funct...
Definition: LALString.c:219
UINT4Vector * XLALCreateUINT4Vector(UINT4 length)
#define XLAL_ERROR_VOID(...)
Macro to invoke a failure from a XLAL routine returning void.
Definition: XLALError.h:726
#define XLAL_ERROR_VAL(val,...)
Macro to invoke the XLALError() function and return with code val (it should not really be used itsel...
Definition: XLALError.h:687
#define XLAL_ERROR_NULL(...)
Macro to invoke a failure from a XLAL routine returning a pointer.
Definition: XLALError.h:713
#define XLAL_ERROR(...)
Macro to invoke a failure from a XLAL routine returning an integer.
Definition: XLALError.h:700
#define XLAL_CHECK(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns an integ...
Definition: XLALError.h:810
#define XLAL_PRINT_DEPRECATION_WARNING(replacement)
Prints a deprecation warning at the "warning" verbosity level.
Definition: XLALError.h:228
@ XLAL_ENOMEM
Memory allocation error.
Definition: XLALError.h:407
@ XLAL_SUCCESS
Success return value (not an error number)
Definition: XLALError.h:401
@ XLAL_EFAULT
Invalid pointer.
Definition: XLALError.h:408
@ XLAL_EFUNC
Internal function call failed bit: "or" this with existing error number.
Definition: XLALError.h:462
@ XLAL_ETYPE
Wrong or unknown type.
Definition: XLALError.h:422
@ XLAL_EIO
I/O error.
Definition: XLALError.h:406
@ XLAL_EINVAL
Invalid argument.
Definition: XLALError.h:409
@ XLAL_EFAILED
Generic failure.
Definition: XLALError.h:418
Epoch relative to GPS epoch, see LIGOTimeGPS type for more details.
Definition: LALDatatypes.h:458
Vector of type UINT4, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:118
UINT4 * data
Pointer to the data array.
Definition: LALDatatypes.h:123
Incomplete type for a pointer to an HDF5 file or group or dataset.
Definition: H5FileIO.h:110