GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ls-hdf5.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2022 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#if defined (HAVE_HDF5)
31
32#include <cctype>
33
34#include <iomanip>
35#include <istream>
36#include <limits>
37#include <ostream>
38#include <string>
39#include <vector>
40
41#include "byte-swap.h"
42#include "data-conv.h"
43#include "file-ops.h"
44#include "glob-match.h"
45#include "lo-mappers.h"
46#include "mach-info.h"
47#include "oct-env.h"
48#include "oct-time.h"
49#include "quit.h"
50#include "str-vec.h"
51#include "oct-locbuf.h"
52
53#include "Cell.h"
54#include "defun.h"
55#include "error.h"
56#include "errwarn.h"
57#include "interpreter.h"
58#include "interpreter-private.h"
59#include "load-save.h"
60#include "oct-hdf5.h"
61#include "ovl.h"
62#include "oct-map.h"
63#include "ov-cell.h"
64#include "pager.h"
65#include "sysdep.h"
66#include "unwind-prot.h"
67#include "utils.h"
68#include "variables.h"
69#include "version.h"
70#include "dMatrix.h"
71#include "ov-lazy-idx.h"
72
73#include "ls-utils.h"
74#include "ls-hdf5.h"
75
76#if defined (HAVE_HDF5)
77
78static hid_t
80{
82 error ("%s: internal error: ID too large for hid_t", who);
83
84 return static_cast<hid_t> (id);
85}
86
87#endif
88
89hdf5_fstreambase::hdf5_fstreambase (const char *name, int mode, int /* prot */)
90 : file_id (-1), current_item (-1)
91{
92#if defined (HAVE_HDF5)
93 open_create (name, mode);
94
95 current_item = 0;
96
97#else
98 err_disabled_feature ("hdf5_fstreambase", "HDF5");
99#endif
100}
101
102void
104{
105#if defined (HAVE_HDF5)
106
107 if (file_id >= 0)
108 {
109 if (H5Fclose (file_id) < 0)
110 std::ios::setstate (std::ios::badbit);
111 file_id = -1;
112 }
113
114#else
115 // This shouldn't happen because construction of hdf5_fstreambase
116 // objects is supposed to be impossible if HDF5 is not available.
117
119#endif
120}
121
122void
123hdf5_fstreambase::open (const char *name, int mode, int)
124{
125#if defined (HAVE_HDF5)
126
127 clear ();
128
129 open_create (name, mode);
130
131 current_item = 0;
132
133#else
134 // This shouldn't happen because construction of hdf5_fstreambase
135 // objects is supposed to be impossible if HDF5 is not available.
136
138#endif
139}
140
141void
142hdf5_fstreambase::open_create (const char *name, int mode)
143{
144#if defined (HAVE_HDF5)
145 // Open the HDF5 file NAME. If it does not exist, create the file.
146
147# if defined (HAVE_HDF5_UTF8)
148 const char *fname = name;
149# else
150 std::string fname_str (name);
151 std::string ascii_fname_str = octave::sys::get_ASCII_filename (fname_str);
152 const char *fname = ascii_fname_str.c_str ();
153# endif
154
155 if (mode & std::ios::in)
156 file_id = H5Fopen (fname, H5F_ACC_RDONLY, octave_H5P_DEFAULT);
157 else if (mode & std::ios::out)
158 {
159 if (mode & std::ios::app && H5Fis_hdf5 (fname) > 0)
160 file_id = H5Fopen (fname, H5F_ACC_RDWR, octave_H5P_DEFAULT);
161 else
162# if defined (HAVE_HDF5_UTF8)
163 file_id = H5Fcreate (fname, H5F_ACC_TRUNC, octave_H5P_DEFAULT,
165# else
166 {
167 // Check whether file already exists
168 std::string abs_ascii_fname
169 = octave::sys::canonicalize_file_name (ascii_fname_str);
170 if (! abs_ascii_fname.empty ())
171 {
172 // Use the existing file
173 file_id = H5Fcreate (fname, H5F_ACC_TRUNC,
175 if (file_id < 0)
176 std::ios::setstate (std::ios::badbit);
177
178 return;
179 }
180
181 // Check whether filename contains non-ASCII (UTF-8) characters.
182 std::string::const_iterator first_non_ASCII
183 = std::find_if (fname_str.begin (), fname_str.end (),
184 [](char c) { return (c < 0 || c >= 128); });
185 if (first_non_ASCII == fname_str.end ())
186 {
187 // No non-ASCII characters
188 file_id = H5Fcreate (name, H5F_ACC_TRUNC, octave_H5P_DEFAULT,
190 if (file_id < 0)
191 std::ios::setstate (std::ios::badbit);
192
193 return;
194 }
195
196 // Create file in temp folder
197 std::string tmp_name = octave::sys::tempnam ("", "oct-");
198 octave_hdf5_id hdf5_fid = H5Fcreate (tmp_name.c_str (), H5F_ACC_TRUNC,
201 if (hdf5_fid < 0)
202 {
203 file_id = -1;
204 std::ios::setstate (std::ios::badbit);
205 return;
206 }
207
208 // Close file
209 H5Fclose (hdf5_fid);
210
211 // Move temporary file to final destination
212 std::string msg;
213 int res = octave::sys::rename (tmp_name, name, msg);
214 if (res < 0)
215 {
216 std::ios::setstate (std::ios::badbit);
217 file_id = -1;
218 return;
219 }
220
221 // Open file at final location
222 ascii_fname_str = octave::sys::get_ASCII_filename (fname_str);
223 ascii_fname = ascii_fname_str.c_str ();
224 file_id = H5Fopen (ascii_fname, H5F_ACC_RDWR, octave_H5P_DEFAULT);
225 }
226# endif
227 }
228 if (file_id < 0)
229 std::ios::setstate (std::ios::badbit);
230
231 return;
232
233#else
234 // This shouldn't happen because construction of hdf5_fstreambase
235 // objects is supposed to be impossible if HDF5 is not available.
236
238#endif
239}
240
241static std::string
242make_valid_identifier (const std::string& nm)
243{
244 std::string retval;
245
246 std::size_t nm_len = nm.length ();
247
248 if (nm_len > 0)
249 {
250 if (! isalpha (nm[0]))
251 retval += '_';
252
253 for (std::size_t i = 0; i < nm_len; i++)
254 {
255 char c = nm[i];
256 retval += (isalnum (c) || c == '_') ? c : '_';
257 }
258 }
259
260 return retval;
261}
262
263// Given two compound types t1 and t2, determine whether they
264// are compatible for reading/writing. This function only
265// works for non-nested types composed of simple elements (ints, floats...),
266// which is all we need it for
267
268bool
270{
271#if defined (HAVE_HDF5)
272
273 int n;
274 if ((n = H5Tget_nmembers (t1)) != H5Tget_nmembers (t2))
275 return false;
276
277 for (int i = 0; i < n; ++i)
278 {
279 hid_t mt1 = H5Tget_member_type (t1, i);
280 hid_t mt2 = H5Tget_member_type (t2, i);
281
282 if (H5Tget_class (mt1) != H5Tget_class (mt2))
283 return false;
284
285 H5Tclose (mt2);
286 H5Tclose (mt1);
287 }
288
289 return true;
290
291#else
292 err_disabled_feature ("hdf5_types_compatible", "HDF5");
293#endif
294}
295
296// Return true if loc_id has the attribute named attr_name, and false
297// otherwise.
298
299bool
300hdf5_check_attr (octave_hdf5_id loc_id, const char *attr_name)
301{
302#if defined (HAVE_HDF5)
303
304 bool retval = false;
305
306 // we have to pull some shenanigans here to make sure
307 // HDF5 doesn't print out all sorts of error messages if we
308 // call H5Aopen for a non-existing attribute
309
310 H5E_auto_t err_func;
311 void *err_func_data;
312
313 // turn off error reporting temporarily, but save the error
314 // reporting function:
315
316#if defined (HAVE_HDF5_18)
317 H5Eget_auto (octave_H5E_DEFAULT, &err_func, &err_func_data);
318 H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr);
319#else
320 H5Eget_auto (&err_func, &err_func_data);
321 H5Eset_auto (nullptr, nullptr);
322#endif
323
324 hid_t attr_id = H5Aopen_name (loc_id, attr_name);
325
326 if (attr_id >= 0)
327 {
328 // successful
329 retval = true;
330 H5Aclose (attr_id);
331 }
332
333 // restore error reporting:
334#if defined (HAVE_HDF5_18)
335 H5Eset_auto (octave_H5E_DEFAULT, err_func, err_func_data);
336#else
337 H5Eset_auto (err_func, err_func_data);
338#endif
339 return retval;
340
341#else
342 err_disabled_feature ("hdf5_check_attr", "HDF5");
343#endif
344}
345
346bool
348 const char *attr_name, void *buf)
349{
350#if defined (HAVE_HDF5)
351
352 bool retval = false;
353
354 // we have to pull some shenanigans here to make sure
355 // HDF5 doesn't print out all sorts of error messages if we
356 // call H5Aopen for a non-existing attribute
357
358 H5E_auto_t err_func;
359 void *err_func_data;
360
361 // turn off error reporting temporarily, but save the error
362 // reporting function:
363
364#if defined (HAVE_HDF5_18)
365 H5Eget_auto (octave_H5E_DEFAULT, &err_func, &err_func_data);
366 H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr);
367#else
368 H5Eget_auto (&err_func, &err_func_data);
369 H5Eset_auto (nullptr, nullptr);
370#endif
371
372 hid_t attr_id = H5Aopen_name (loc_id, attr_name);
373
374 if (attr_id >= 0)
375 {
376 hid_t space_id = H5Aget_space (attr_id);
377
378 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
379
380 if (rank == 0)
381 retval = H5Aread (attr_id, type_id, buf) >= 0;
382 H5Aclose (attr_id);
383 }
384
385 // restore error reporting:
386#if defined (HAVE_HDF5_18)
387 H5Eset_auto (octave_H5E_DEFAULT, err_func, err_func_data);
388#else
389 H5Eset_auto (err_func, err_func_data);
390#endif
391 return retval;
392
393#else
394 err_disabled_feature ("hdf5_get_scalar_attr", "HDF5");
395#endif
396}
397
398// The following subroutines creates an HDF5 representations of the way
399// we will store Octave complex types (pairs of floating-point numbers).
400// NUM_TYPE is the HDF5 numeric type to use for storage (e.g.
401// H5T_NATIVE_DOUBLE to save as 'double'). Note that any necessary
402// conversions are handled automatically by HDF5.
403
406{
407#if defined (HAVE_HDF5)
408
409 hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 2);
410
411 H5Tinsert (type_id, "real", 0 * sizeof (double), num_type);
412 H5Tinsert (type_id, "imag", 1 * sizeof (double), num_type);
413
414 return type_id;
415
416#else
417 err_disabled_feature ("hdf5_make_complex_type", "HDF5");
418#endif
419}
420
421#if defined (HAVE_HDF5)
422
423// The following subroutine creates an HDF5 representation of the way
424// we will store Octave range types (triplets of floating-point numbers).
425// NUM_TYPE is the HDF5 numeric type to use for storage
426// (e.g., H5T_NATIVE_DOUBLE to save as 'double').
427// Note that any necessary conversions are handled automatically by HDF5.
428
429static hid_t
430hdf5_make_range_type (hid_t num_type)
431{
432 hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 3);
433
434 H5Tinsert (type_id, "base", 0 * sizeof (double), num_type);
435 H5Tinsert (type_id, "limit", 1 * sizeof (double), num_type);
436 H5Tinsert (type_id, "increment", 2 * sizeof (double), num_type);
437
438 return type_id;
439}
440
441static herr_t
442load_inline_fcn (hid_t loc_id, const char *name, octave_value& retval)
443{
444#if defined (HAVE_HDF5)
445
446 hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id;
447 hsize_t rank;
448 int slen;
449
450#if defined (HAVE_HDF5_18)
451 group_hid = H5Gopen (loc_id, name, octave_H5P_DEFAULT);
452#else
453 group_hid = H5Gopen (loc_id, name);
454#endif
455 if (group_hid < 0) return -1;
456
457#if defined (HAVE_HDF5_18)
458 data_hid = H5Dopen (group_hid, "args", octave_H5P_DEFAULT);
459#else
460 data_hid = H5Dopen (group_hid, "args");
461#endif
462 space_hid = H5Dget_space (data_hid);
463 rank = H5Sget_simple_extent_ndims (space_hid);
464
465 if (rank != 2)
466 {
467 H5Dclose (data_hid);
468 H5Sclose (space_hid);
469 H5Gclose (group_hid);
470 return -1;
471 }
472
473 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank);
474 OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank);
475
476 H5Sget_simple_extent_dims (space_hid, hdims, maxdims);
477
478 octave_value_list args (hdims[1]+1);
479
480 OCTAVE_LOCAL_BUFFER (char, s1, hdims[0] * hdims[1]);
481
482 if (H5Dread (data_hid, H5T_NATIVE_UCHAR, octave_H5S_ALL, octave_H5S_ALL,
483 octave_H5P_DEFAULT, s1) < 0)
484 {
485 H5Dclose (data_hid);
486 H5Sclose (space_hid);
487 H5Gclose (group_hid);
488 return -1;
489 }
490
491 H5Dclose (data_hid);
492 H5Sclose (space_hid);
493
494 for (std::size_t i = 0; i < hdims[1]; i++)
495 args(i+1) = std::string (s1 + i*hdims[0]);
496
497#if defined (HAVE_HDF5_18)
498 data_hid = H5Dopen (group_hid, "nm", octave_H5P_DEFAULT);
499#else
500 data_hid = H5Dopen (group_hid, "nm");
501#endif
502
503 if (data_hid < 0)
504 {
505 H5Gclose (group_hid);
506 return -1;
507 }
508
509 type_hid = H5Dget_type (data_hid);
510 type_class_hid = H5Tget_class (type_hid);
511
512 if (type_class_hid != H5T_STRING)
513 {
514 H5Tclose (type_hid);
515 H5Dclose (data_hid);
516 H5Gclose (group_hid);
517 return -1;
518 }
519
520 space_hid = H5Dget_space (data_hid);
521 rank = H5Sget_simple_extent_ndims (space_hid);
522
523 if (rank != 0)
524 {
525 H5Sclose (space_hid);
526 H5Tclose (type_hid);
527 H5Dclose (data_hid);
528 H5Gclose (group_hid);
529 return -1;
530 }
531
532 slen = H5Tget_size (type_hid);
533 if (slen < 0)
534 {
535 H5Sclose (space_hid);
536 H5Tclose (type_hid);
537 H5Dclose (data_hid);
538 H5Gclose (group_hid);
539 return -1;
540 }
541
542 OCTAVE_LOCAL_BUFFER (char, nm_tmp, slen);
543
544 // create datatype for (null-terminated) string to read into:
545 st_id = H5Tcopy (H5T_C_S1);
546 H5Tset_size (st_id, slen);
547
548 if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL,
549 octave_H5P_DEFAULT, nm_tmp) < 0)
550 {
551 H5Sclose (space_hid);
552 H5Tclose (type_hid);
553 H5Gclose (group_hid);
554 return -1;
555 }
556 H5Tclose (st_id);
557 H5Dclose (data_hid);
558 // NAME is obsolete and unused.
559 // std::string name (nm_tmp);
560
561#if defined (HAVE_HDF5_18)
562 data_hid = H5Dopen (group_hid, "iftext", octave_H5P_DEFAULT);
563#else
564 data_hid = H5Dopen (group_hid, "iftext");
565#endif
566
567 if (data_hid < 0)
568 {
569 H5Gclose (group_hid);
570 return -1;
571 }
572
573 type_hid = H5Dget_type (data_hid);
574 type_class_hid = H5Tget_class (type_hid);
575
576 if (type_class_hid != H5T_STRING)
577 {
578 H5Tclose (type_hid);
579 H5Dclose (data_hid);
580 H5Gclose (group_hid);
581 return -1;
582 }
583
584 space_hid = H5Dget_space (data_hid);
585 rank = H5Sget_simple_extent_ndims (space_hid);
586
587 if (rank != 0)
588 {
589 H5Sclose (space_hid);
590 H5Tclose (type_hid);
591 H5Dclose (data_hid);
592 H5Gclose (group_hid);
593 return -1;
594 }
595
596 slen = H5Tget_size (type_hid);
597 if (slen < 0)
598 {
599 H5Sclose (space_hid);
600 H5Tclose (type_hid);
601 H5Dclose (data_hid);
602 H5Gclose (group_hid);
603 return -1;
604 }
605
606 OCTAVE_LOCAL_BUFFER (char, iftext_tmp, slen);
607
608 // create datatype for (null-terminated) string to read into:
609 st_id = H5Tcopy (H5T_C_S1);
610 H5Tset_size (st_id, slen);
611
612 if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL,
613 octave_H5P_DEFAULT, iftext_tmp) < 0)
614 {
615 H5Sclose (space_hid);
616 H5Tclose (type_hid);
617 H5Gclose (group_hid);
618 return -1;
619 }
620 H5Tclose (st_id);
621 H5Dclose (data_hid);
622
623 args(0) = std::string (iftext_tmp);
624
625 octave::interpreter& interp
626 = octave::__get_interpreter__ ("load_inline_fcn");
627
628 octave_value_list tmp = interp.feval ("inline", args, 1);
629
630 if (tmp.length () > 0)
631 {
632 retval = tmp(0);
633 return 1;
634 }
635
636#else
637 octave_unused_parameter (loc_id);
638 octave_unused_parameter (name);
639 octave_unused_parameter (retval);
640
641 warn_load ("hdf5");
642#endif
643
644 return -1;
645}
646
647// This function is designed to be passed to H5Giterate, which calls it
648// on each data item in an HDF5 file. For the item whose name is NAME in
649// the group GROUP_ID, this function sets dv->tc to an Octave representation
650// of that item. (dv must be a pointer to hdf5_callback_data.) (It also
651// sets the other fields of dv).
652//
653// It returns 1 on success (in which case H5Giterate stops and returns),
654// -1 on error, and 0 to tell H5Giterate to continue on to the next item
655// (e.g., if NAME was a data type we don't recognize).
656//
657// This function must not throw an exception.
658
659static herr_t
660hdf5_read_next_data_internal (hid_t group_id, const char *name, void *dv)
661{
662 hdf5_callback_data *d = static_cast<hdf5_callback_data *> (dv);
663 hid_t type_id = -1;
664 hid_t type_class_id = -1;
665 hid_t data_id = -1;
666 hid_t subgroup_id = -1;
667 hid_t space_id = -1;;
668
669 H5G_stat_t info;
670 herr_t retval = 0;
671 bool ident_valid = octave::valid_identifier (name);
672
673 std::string vname = name;
674
675 octave::type_info& type_info
676 = octave::__get_type_info__ ("hdf5_read_next_data_internal");
677
678 // Allow identifiers as all digits so we can load lists saved by
679 // earlier versions of Octave.
680
681 if (! ident_valid)
682 {
683 // fix the identifier, replacing invalid chars with underscores
684 vname = make_valid_identifier (vname);
685
686 // check again (in case vname was null, empty, or some such thing):
687 ident_valid = octave::valid_identifier (vname);
688 }
689
690 H5Gget_objinfo (group_id, name, 1, &info);
691
692 if (info.type == H5G_GROUP && ident_valid)
693 {
694#if defined (HAVE_HDF5_18)
695 subgroup_id = H5Gopen (group_id, name, octave_H5P_DEFAULT);
696#else
697 subgroup_id = H5Gopen (group_id, name);
698#endif
699
700 if (subgroup_id < 0)
701 {
702 retval = subgroup_id;
703 goto done;
704 }
705
706 if (hdf5_check_attr (subgroup_id, "OCTAVE_NEW_FORMAT"))
707 {
708#if defined (HAVE_HDF5_18)
709 data_id = H5Dopen (subgroup_id, "type", octave_H5P_DEFAULT);
710#else
711 data_id = H5Dopen (subgroup_id, "type");
712#endif
713
714 if (data_id < 0)
715 {
716 retval = data_id;
717 goto done;
718 }
719
720 type_id = H5Dget_type (data_id);
721
722 type_class_id = H5Tget_class (type_id);
723
724 if (type_class_id != H5T_STRING)
725 goto done;
726
727 space_id = H5Dget_space (data_id);
728 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
729
730 if (rank != 0)
731 goto done;
732
733 int slen = H5Tget_size (type_id);
734 if (slen < 0)
735 goto done;
736
737 OCTAVE_LOCAL_BUFFER (char, typ, slen);
738
739 // create datatype for (null-terminated) string to read into:
740 hid_t st_id = H5Tcopy (H5T_C_S1);
741 H5Tset_size (st_id, slen);
742
743 if (H5Dread (data_id, st_id, octave_H5S_ALL, octave_H5S_ALL,
744 octave_H5P_DEFAULT, typ) < 0)
745 goto done;
746
747 H5Tclose (st_id);
748 H5Dclose (data_id);
749
750 if (std::string (typ, slen-1) == "inline function")
751 {
752 retval = load_inline_fcn (subgroup_id, name, d->tc);
753 }
754 else
755 {
756 d->tc = type_info.lookup_type (std::string (typ, slen-1));
757
758 try
759 {
760 retval = (d->tc.load_hdf5 (subgroup_id, "value") ? 1 : -1);
761 }
762 catch (const octave::execution_exception& ee)
763 {
764 retval = -1;
765 }
766 }
767
768 // check for OCTAVE_GLOBAL attribute:
769 d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
770
771 H5Gclose (subgroup_id);
772 }
773 else
774 {
775 // It seems that this block only applies to an old list type
776 // and that we shouldn't need to handle the old inline
777 // function type here.
778
779 // an HDF5 group is treated as an octave structure by
780 // default (since that preserves name information), and an
781 // octave list otherwise.
782
783 if (hdf5_check_attr (subgroup_id, "OCTAVE_LIST"))
784 d->tc = type_info.lookup_type ("list");
785 else
786 d->tc = type_info.lookup_type ("struct");
787
788 // check for OCTAVE_GLOBAL attribute:
789 d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
790
791 H5Gclose (subgroup_id);
792
793 try
794 {
795 retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
796 }
797 catch (const octave::execution_exception& ee)
798 {
799 retval = -1;
800 }
801 }
802
803 }
804 else if (info.type == H5G_DATASET && ident_valid)
805 {
806 // It seems that this block only applies to an old version of
807 // Octave HDF5 files and that it is probably not important to
808 // handle the old inline function type here.
809
810 // For backwards compatibility.
811#if defined (HAVE_HDF5_18)
812 data_id = H5Dopen (group_id, name, octave_H5P_DEFAULT);
813#else
814 data_id = H5Dopen (group_id, name);
815#endif
816
817 if (data_id < 0)
818 {
819 retval = data_id;
820 goto done;
821 }
822
823 type_id = H5Dget_type (data_id);
824
825 type_class_id = H5Tget_class (type_id);
826
827 if (type_class_id == H5T_FLOAT)
828 {
829 space_id = H5Dget_space (data_id);
830
831 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
832
833 if (rank == 0)
834 d->tc = type_info.lookup_type ("scalar");
835 else
836 d->tc = type_info.lookup_type ("matrix");
837
838 H5Sclose (space_id);
839 }
840 else if (type_class_id == H5T_INTEGER)
841 {
842 // What integer type do we really have..
843 std::string int_typ;
844#if defined (HAVE_H5T_GET_NATIVE_TYPE)
845 // FIXME: test this code and activated with an autoconf
846 // test!! It is also incorrect for 64-bit indexing!!
847
848 switch (H5Tget_native_type (type_id, H5T_DIR_ASCEND))
849 {
850 case H5T_NATIVE_CHAR:
851 int_typ = "int8 ";
852 break;
853
854 case H5T_NATIVE_SHORT:
855 int_typ = "int16 ";
856 break;
857
858 case H5T_NATIVE_INT:
859 case H5T_NATIVE_LONG:
860 int_typ = "int32 ";
861 break;
862
863 case H5T_NATIVE_LLONG:
864 int_typ = "int64 ";
865 break;
866
867 case H5T_NATIVE_UCHAR:
868 int_typ = "uint8 ";
869 break;
870
871 case H5T_NATIVE_USHORT:
872 int_typ = "uint16 ";
873 break;
874
875 case H5T_NATIVE_UINT:
876 case H5T_NATIVE_ULONG:
877 int_typ = "uint32 ";
878 break;
879
880 case H5T_NATIVE_ULLONG:
881 int_typ = "uint64 ";
882 break;
883 }
884#else
885 hid_t int_sign = H5Tget_sign (type_id);
886
887 if (int_sign == H5T_SGN_ERROR)
888 warning ("load: can't read '%s' (unknown datatype)", name);
889 else
890 {
891 if (int_sign == H5T_SGN_NONE)
892 int_typ.push_back ('u');
893 int_typ.append ("int");
894
895 int slen = H5Tget_size (type_id);
896 if (slen < 0)
897 warning ("load: can't read '%s' (unknown datatype)", name);
898 else
899 {
900 switch (slen)
901 {
902 case 1:
903 int_typ.append ("8 ");
904 break;
905
906 case 2:
907 int_typ.append ("16 ");
908 break;
909
910 case 4:
911 int_typ.append ("32 ");
912 break;
913
914 case 8:
915 int_typ.append ("64 ");
916 break;
917
918 default:
919 warning ("load: can't read '%s' (unknown datatype)",
920 name);
921 int_typ = "";
922 break;
923 }
924 }
925 }
926#endif
927 if (int_typ == "")
928 warning ("load: can't read '%s' (unknown datatype)", name);
929 else
930 {
931 // Matrix or scalar?
932 space_id = H5Dget_space (data_id);
933
934 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
935
936 if (rank == 0)
937 int_typ.append ("scalar");
938 else
939 int_typ.append ("matrix");
940
941 d->tc = type_info.lookup_type (int_typ);
942 H5Sclose (space_id);
943 }
944 }
945 else if (type_class_id == H5T_STRING)
946 d->tc = type_info.lookup_type ("string");
947 else if (type_class_id == H5T_COMPOUND)
948 {
949 hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
950 hid_t range_type = hdf5_make_range_type (H5T_NATIVE_DOUBLE);
951
952 if (hdf5_types_compatible (type_id, complex_type))
953 {
954 // read complex matrix or scalar variable
955 space_id = H5Dget_space (data_id);
956 hsize_t rank = H5Sget_simple_extent_ndims (space_id);
957
958 if (rank == 0)
959 d->tc = type_info.lookup_type ("complex scalar");
960 else
961 d->tc = type_info.lookup_type ("complex matrix");
962
963 H5Sclose (space_id);
964 }
965 else if (hdf5_types_compatible (type_id, range_type))
966 {
967 // If it's not a complex, check if it's a range
969 }
970 else // Otherwise, just ignore it with a warning.
971 {
972 warning ("load: can't read '%s' (unknown datatype)", name);
973 retval = 0; // unknown datatype; skip
974 return retval;
975 }
976
977 H5Tclose (range_type);
978 H5Tclose (complex_type);
979 }
980 else
981 {
982 warning ("load: can't read '%s' (unknown datatype)", name);
983 retval = 0; // unknown datatype; skip
984 return retval;
985 }
986
987 // check for OCTAVE_GLOBAL attribute:
988 d->global = hdf5_check_attr (data_id, "OCTAVE_GLOBAL");
989
990 try
991 {
992 retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
993 }
994 catch (const octave::execution_exception& ee)
995 {
996 retval = -1;
997 }
998
999 H5Tclose (type_id);
1000 H5Dclose (data_id);
1001 }
1002
1003 if (! ident_valid)
1004 {
1005 // should we attempt to handle invalid identifiers by converting
1006 // bad characters to '_', say?
1007 warning ("load: skipping invalid identifier '%s' in hdf5 file",
1008 name);
1009 }
1010
1011done:
1012 if (retval < 0)
1013 {
1014 // Must be warning. A call to error aborts and leaves H5Giterate in
1015 // a mangled state that causes segfault on exit (bug #56149).
1016 warning ("load: error while reading hdf5 item '%s'", name);
1017 }
1018
1019 if (retval > 0)
1020 {
1021 // get documentation string, if any:
1022 int comment_length = H5Gget_comment (group_id, name, 0, nullptr);
1023
1024 if (comment_length > 1)
1025 {
1026 OCTAVE_LOCAL_BUFFER (char, tdoc, comment_length);
1027 H5Gget_comment (group_id, name, comment_length, tdoc);
1028 d->doc = tdoc;
1029 }
1030 else if (vname != name)
1031 {
1032 // the name was changed; store the original name
1033 // as the documentation string:
1034 d->doc = name;
1035 }
1036
1037 // copy name (actually, vname):
1038 d->name = vname;
1039 }
1040
1041 return retval;
1042}
1043
1044#endif
1045
1047hdf5_read_next_data (octave_hdf5_id group_id, const char *name, void *dv)
1048{
1049#if defined (HAVE_HDF5)
1050
1051 hid_t new_id = check_hdf5_id_value (group_id, "hdf5_read_next_data");
1052
1053 return hdf5_read_next_data_internal (new_id, name, dv);
1054
1055#else
1056 err_disabled_feature ("hdf5_read_next_data", "HDF5");
1057#endif
1058}
1059
1061hdf5_h5g_iterate (octave_hdf5_id loc_id, const char *name, int *idx,
1062 void *operator_data)
1063{
1064#if defined (HAVE_HDF5)
1065
1066 hid_t new_id = check_hdf5_id_value (loc_id, "hdf5_h5g_iterate");
1067
1068 return H5Giterate (new_id, name, idx, hdf5_read_next_data_internal,
1069 operator_data);
1070
1071#else
1072 err_disabled_feature ("hdf5_h5g_iterate", "HDF5");
1073#endif
1074}
1075
1076// Read the next Octave variable from the stream IS, which must really be an
1077// hdf5_ifstream. Return the variable value in tc, its docstring in doc, and
1078// whether it is global in global. The return value is the name of the
1079// variable, or NULL if none were found or there was an error.
1080std::string
1081read_hdf5_data (std::istream& is, const std::string& /* filename */,
1082 bool& global, octave_value& tc, std::string& doc,
1083 const string_vector& argv, int argv_idx, int argc)
1084{
1085#if defined (HAVE_HDF5)
1086
1088
1089 std::string retval;
1090
1091 doc.clear ();
1092
1093 hdf5_ifstream& hs = dynamic_cast<hdf5_ifstream&> (is);
1095
1096 herr_t H5Giterate_retval = -1;
1097
1098 hsize_t num_obj = 0;
1099#if defined (HAVE_HDF5_18)
1100 hid_t group_id = H5Gopen (hs.file_id, "/", octave_H5P_DEFAULT);
1101#else
1102 hid_t group_id = H5Gopen (hs.file_id, "/");
1103#endif
1104 H5Gget_num_objs (group_id, &num_obj);
1105 H5Gclose (group_id);
1106
1107 // For large datasets and out-of-core functionality,
1108 // check if only parts of the data is requested
1109 bool load_named_vars = argv_idx < argc;
1110 while (load_named_vars && hs.current_item < static_cast<int> (num_obj))
1111 {
1112 std::vector<char> var_name;
1113 bool found = false;
1114 std::size_t len = 0;
1115
1116 len = H5Gget_objname_by_idx (hs.file_id, hs.current_item, nullptr, 0);
1117 var_name.resize (len+1);
1118 H5Gget_objname_by_idx (hs.file_id, hs.current_item, &var_name[0], len+1);
1119
1120 for (int i = argv_idx; i < argc; i++)
1121 {
1122 glob_match pattern (argv[i]);
1123 if (pattern.match (std::string (&var_name[0])))
1124 {
1125 found = true;
1126 break;
1127 }
1128 }
1129
1130 if (found)
1131 break;
1132
1133 hs.current_item++;
1134 }
1135
1136 if (hs.current_item < static_cast<int> (num_obj))
1137 H5Giterate_retval = H5Giterate (hs.file_id, "/", &hs.current_item,
1139
1140 if (H5Giterate_retval > 0)
1141 {
1142 global = d.global;
1143 tc = d.tc;
1144 doc = d.doc;
1145 }
1146 else
1147 {
1148 // An error occurred (H5Giterate_retval < 0),
1149 // or there are no more datasets (H5Giterate_retval == 0).
1150 // hdf5_read_next_data_internal has already printed a warning msg.
1151 }
1152
1153 if (! d.name.empty ())
1154 retval = d.name;
1155
1156 return retval;
1157
1158#else
1159 err_disabled_feature ("read_hdf5_data", "HDF5");
1160#endif
1161}
1162
1163// Add an attribute named attr_name to loc_id (a simple scalar
1164// attribute with value 1). Return value is >= 0 on success.
1166hdf5_add_attr (octave_hdf5_id loc_id, const char *attr_name)
1167{
1168#if defined (HAVE_HDF5)
1169
1170 herr_t retval = 0;
1171
1172 hid_t as_id = H5Screate (H5S_SCALAR);
1173
1174 if (as_id >= 0)
1175 {
1176#if defined (HAVE_HDF5_18)
1177 hid_t a_id = H5Acreate (loc_id, attr_name, H5T_NATIVE_UCHAR,
1179#else
1180 hid_t a_id = H5Acreate (loc_id, attr_name,
1181 H5T_NATIVE_UCHAR, as_id, octave_H5P_DEFAULT);
1182#endif
1183 if (a_id >= 0)
1184 {
1185 unsigned char attr_val = 1;
1186
1187 retval = H5Awrite (a_id, H5T_NATIVE_UCHAR, &attr_val);
1188
1189 H5Aclose (a_id);
1190 }
1191 else
1192 retval = a_id;
1193
1194 H5Sclose (as_id);
1195 }
1196 else
1197 retval = as_id;
1198
1199 return retval;
1200
1201#else
1202 err_disabled_feature ("hdf5_add_attr", "HDF5");
1203#endif
1204}
1205
1208 const char *attr_name, void *buf)
1209{
1210#if defined (HAVE_HDF5)
1211
1212 herr_t retval = 0;
1213
1214 hid_t as_id = H5Screate (H5S_SCALAR);
1215
1216 if (as_id >= 0)
1217 {
1218#if defined (HAVE_HDF5_18)
1219 hid_t a_id = H5Acreate (loc_id, attr_name, type_id,
1221#else
1222 hid_t a_id = H5Acreate (loc_id, attr_name,
1223 type_id, as_id, octave_H5P_DEFAULT);
1224#endif
1225 if (a_id >= 0)
1226 {
1227 retval = H5Awrite (a_id, type_id, buf);
1228
1229 H5Aclose (a_id);
1230 }
1231 else
1232 retval = a_id;
1233
1234 H5Sclose (as_id);
1235 }
1236 else
1237 retval = as_id;
1238
1239 return retval;
1240
1241#else
1242 err_disabled_feature ("hdf5_add_scalar_attr", "HDF5");
1243#endif
1244}
1245
1246// Save an empty matrix, if needed. Returns
1247// > 0 Saved empty matrix
1248// = 0 Not an empty matrix; did nothing
1249// < 0 Error condition
1250int
1251save_hdf5_empty (octave_hdf5_id loc_id, const char *name, const dim_vector& d)
1252{
1253#if defined (HAVE_HDF5)
1254
1255 hsize_t sz = d.length ();
1257 bool empty = false;
1258 hid_t space_hid = -1;
1259 hid_t data_hid = -1;
1260 int retval;
1261 for (hsize_t i = 0; i < sz; i++)
1262 {
1263 dims[i] = d(i);
1264 if (dims[i] < 1)
1265 empty = true;
1266 }
1267
1268 if (! empty)
1269 return 0;
1270
1271 space_hid = H5Screate_simple (1, &sz, nullptr);
1272 if (space_hid < 0) return space_hid;
1273#if defined (HAVE_HDF5_18)
1274 data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,
1276#else
1277 data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,
1279#endif
1280 if (data_hid < 0)
1281 {
1282 H5Sclose (space_hid);
1283 return data_hid;
1284 }
1285
1286 retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
1287 octave_H5P_DEFAULT, dims) >= 0;
1288
1289 H5Dclose (data_hid);
1290 H5Sclose (space_hid);
1291
1292 if (retval)
1293 retval = hdf5_add_attr (loc_id, "OCTAVE_EMPTY_MATRIX");
1294
1295 return (retval == 0 ? 1 : retval);
1296
1297#else
1298 err_disabled_feature ("save_hdf5_empty", "HDF5");
1299#endif
1300}
1301
1302// Load an empty matrix, if needed. Returns
1303// > 0 loaded empty matrix, dimensions returned
1304// = 0 Not an empty matrix; did nothing
1305// < 0 Error condition
1306int
1308{
1309#if defined (HAVE_HDF5)
1310
1311 if (! hdf5_check_attr (loc_id, "OCTAVE_EMPTY_MATRIX"))
1312 return 0;
1313
1314 hsize_t hdims, maxdims;
1315#if defined (HAVE_HDF5_18)
1316 hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);
1317#else
1318 hid_t data_hid = H5Dopen (loc_id, name);
1319#endif
1320 hid_t space_id = H5Dget_space (data_hid);
1321 H5Sget_simple_extent_dims (space_id, &hdims, &maxdims);
1322 int retval;
1323
1324 OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, hdims);
1325
1326 retval = H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
1327 octave_H5P_DEFAULT, dims);
1328 if (retval >= 0)
1329 {
1330 d.resize (hdims);
1331 for (hsize_t i = 0; i < hdims; i++)
1332 d(i) = dims[i];
1333 }
1334
1335 H5Sclose (space_id);
1336 H5Dclose (data_hid);
1337
1338 return (retval == 0 ? hdims : retval);
1339
1340#else
1341 err_disabled_feature ("load_hdf5_empty", "HDF5");
1342#endif
1343}
1344
1345// save_type_to_hdf5 is not currently used, since hdf5 doesn't yet support
1346// automatic float<->integer conversions:
1347
1348// return the HDF5 type id corresponding to the Octave save_type
1349
1352{
1353#if defined (HAVE_HDF5)
1354# if defined (HAVE_HDF5_INT2FLOAT_CONVERSIONS)
1355
1356 switch (st)
1357 {
1358 case LS_U_CHAR:
1359 return H5T_NATIVE_UCHAR;
1360
1361 case LS_U_SHORT:
1362 return H5T_NATIVE_USHORT;
1363
1364 case LS_U_INT:
1365 return H5T_NATIVE_UINT;
1366
1367 case LS_CHAR:
1368 return H5T_NATIVE_CHAR;
1369
1370 case LS_SHORT:
1371 return H5T_NATIVE_SHORT;
1372
1373 case LS_INT:
1374 return H5T_NATIVE_INT;
1375
1376 case LS_FLOAT:
1377 return H5T_NATIVE_FLOAT;
1378
1379 case LS_DOUBLE:
1380 default:
1381 return H5T_NATIVE_DOUBLE;
1382 }
1383
1384# else
1385
1386 octave_unused_parameter (st);
1387
1388 return -1;
1389
1390# endif
1391
1392#else
1393
1394 octave_unused_parameter (st);
1395
1396 err_disabled_feature ("save_type_to_hdf5", "HDF5");
1397
1398#endif
1399}
1400
1401// Add the data from TC to the HDF5 location loc_id, which could
1402// be either a file or a group within a file. Return true if
1403// successful. This function calls itself recursively for lists
1404// (stored as HDF5 groups).
1405
1406bool
1408 const std::string& name, const std::string& doc,
1409 bool mark_global, bool save_as_floats)
1410{
1411#if defined (HAVE_HDF5)
1412
1413 hsize_t dims[3];
1414 hid_t type_id, space_id, data_id, data_type_id;
1415 type_id = space_id = data_id = data_type_id = -1;
1416
1417 bool retval = false;
1418 octave_value val = tc;
1419 // FIXME: diagonal & permutation matrices currently don't know how to save
1420 // themselves, so we convert them first to normal matrices using A = A(:,:).
1421 // This is a temporary hack.
1422 if (val.is_diag_matrix () || val.is_perm_matrix ()
1424 val = val.full_value ();
1425
1426 std::string t = val.type_name ();
1427#if defined (HAVE_HDF5_18)
1428 data_id = H5Gcreate (loc_id, name.c_str (), octave_H5P_DEFAULT,
1430#else
1431 data_id = H5Gcreate (loc_id, name.c_str (), 0);
1432#endif
1433 if (data_id < 0)
1434 goto error_cleanup;
1435
1436 // attach the type of the variable
1437 type_id = H5Tcopy (H5T_C_S1); H5Tset_size (type_id, t.length () + 1);
1438 if (type_id < 0)
1439 goto error_cleanup;
1440
1441 dims[0] = 0;
1442 space_id = H5Screate_simple (0, dims, nullptr);
1443 if (space_id < 0)
1444 goto error_cleanup;
1445#if defined (HAVE_HDF5_18)
1446 data_type_id = H5Dcreate (data_id, "type", type_id, space_id,
1449#else
1450 data_type_id = H5Dcreate (data_id, "type", type_id, space_id,
1452#endif
1453 if (data_type_id < 0
1454 || H5Dwrite (data_type_id, type_id, octave_H5S_ALL, octave_H5S_ALL,
1455 octave_H5P_DEFAULT, t.c_str ()) < 0)
1456 goto error_cleanup;
1457
1458 // Now call the real function to save the variable
1459 retval = val.save_hdf5 (data_id, "value", save_as_floats);
1460
1461 // attach doc string as comment:
1462 if (retval && doc.length () > 0
1463 && H5Gset_comment (loc_id, name.c_str (), doc.c_str ()) < 0)
1464 retval = false;
1465
1466 // if it's global, add an attribute "OCTAVE_GLOBAL" with value 1
1467 if (retval && mark_global)
1468 retval = hdf5_add_attr (data_id, "OCTAVE_GLOBAL") >= 0;
1469
1470 // We are saving in the new variable format, so mark it
1471 if (retval)
1472 retval = hdf5_add_attr (data_id, "OCTAVE_NEW_FORMAT") >= 0;
1473
1474error_cleanup:
1475
1476 if (data_type_id >= 0)
1477 H5Dclose (data_type_id);
1478
1479 if (type_id >= 0)
1480 H5Tclose (type_id);
1481
1482 if (space_id >= 0)
1483 H5Sclose (space_id);
1484
1485 if (data_id >= 0)
1486 H5Gclose (data_id);
1487
1488 if (! retval)
1489 error ("save: error while writing '%s' to hdf5 file", name.c_str ());
1490
1491 return retval;
1492
1493#else
1494 err_disabled_feature ("add_hdf5_data", "HDF5");
1495#endif
1496}
1497
1498// Write data from TC in HDF5 (binary) format to the stream OS,
1499// which must be an hdf5_ofstream, returning true on success.
1500
1501bool
1502save_hdf5_data (std::ostream& os, const octave_value& tc,
1503 const std::string& name, const std::string& doc,
1504 bool mark_global, bool save_as_floats)
1505{
1506#if defined (HAVE_HDF5)
1507
1509
1510 hdf5_ofstream& hs = dynamic_cast<hdf5_ofstream&> (os);
1511
1512 return add_hdf5_data (hs.file_id, tc, name, doc,
1513 mark_global, save_as_floats);
1514
1515#else
1516 err_disabled_feature ("save_hdf5_data", "HDF5");
1517#endif
1518}
1519
1520#endif
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
bool match(const std::string &str) const
Definition: glob-match.cc:35
OCTINTERP_API void open(const char *name, int mode, int)
Definition: ls-hdf5.cc:123
OCTINTERP_API void open_create(const char *name, int mode)
Definition: ls-hdf5.cc:142
octave_hdf5_id file_id
Definition: ls-hdf5.h:47
OCTINTERP_API void close(void)
Definition: ls-hdf5.cc:103
int current_item
Definition: ls-hdf5.h:50
static int static_type_id(void)
Definition: ov-lazy-idx.h:279
octave_idx_type length(void) const
Definition: ovl.h:113
int type_id(void) const
Definition: ov.h:1447
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
Definition: ov.h:1497
octave_value full_value(void) const
Definition: ov.h:489
bool is_diag_matrix(void) const
Definition: ov.h:676
bool is_perm_matrix(void) const
Definition: ov.h:679
std::string type_name(void) const
Definition: ov.h:1449
octave_value lookup_type(const std::string &nm)
Definition: ov-typeinfo.cc:480
const octave_hdf5_id octave_H5P_DEFAULT
const octave_hdf5_id octave_H5E_DEFAULT
const octave_hdf5_id octave_H5S_ALL
save_type
Definition: data-conv.h:87
@ LS_U_CHAR
Definition: data-conv.h:88
@ LS_DOUBLE
Definition: data-conv.h:95
@ LS_U_SHORT
Definition: data-conv.h:89
@ LS_FLOAT
Definition: data-conv.h:94
@ LS_SHORT
Definition: data-conv.h:92
@ LS_CHAR
Definition: data-conv.h:91
@ LS_INT
Definition: data-conv.h:93
@ LS_U_INT
Definition: data-conv.h:90
void warning(const char *fmt,...)
Definition: error.cc:1055
void error(const char *fmt,...)
Definition: error.cc:980
#define panic_impossible()
Definition: error.h:411
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition: errwarn.cc:53
QString name
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
bool save_hdf5_data(std::ostream &os, const octave_value &tc, const std::string &name, const std::string &doc, bool mark_global, bool save_as_floats)
Definition: ls-hdf5.cc:1502
static herr_t hdf5_read_next_data_internal(hid_t group_id, const char *name, void *dv)
Definition: ls-hdf5.cc:660
int save_hdf5_empty(octave_hdf5_id loc_id, const char *name, const dim_vector &d)
Definition: ls-hdf5.cc:1251
std::string read_hdf5_data(std::istream &is, const std::string &, bool &global, octave_value &tc, std::string &doc, const string_vector &argv, int argv_idx, int argc)
Definition: ls-hdf5.cc:1081
octave_hdf5_err hdf5_add_attr(octave_hdf5_id loc_id, const char *attr_name)
Definition: ls-hdf5.cc:1166
bool hdf5_get_scalar_attr(octave_hdf5_id loc_id, octave_hdf5_id type_id, const char *attr_name, void *buf)
Definition: ls-hdf5.cc:347
int load_hdf5_empty(octave_hdf5_id loc_id, const char *name, dim_vector &d)
Definition: ls-hdf5.cc:1307
octave_hdf5_id save_type_to_hdf5(save_type st)
Definition: ls-hdf5.cc:1351
octave_hdf5_id hdf5_make_complex_type(octave_hdf5_id num_type)
Definition: ls-hdf5.cc:405
static hid_t hdf5_make_range_type(hid_t num_type)
Definition: ls-hdf5.cc:430
static herr_t load_inline_fcn(hid_t loc_id, const char *name, octave_value &retval)
Definition: ls-hdf5.cc:442
octave_hdf5_err hdf5_read_next_data(octave_hdf5_id group_id, const char *name, void *dv)
Definition: ls-hdf5.cc:1047
octave_hdf5_err hdf5_h5g_iterate(octave_hdf5_id loc_id, const char *name, int *idx, void *operator_data)
Definition: ls-hdf5.cc:1061
bool hdf5_types_compatible(octave_hdf5_id t1, octave_hdf5_id t2)
Definition: ls-hdf5.cc:269
octave_hdf5_err hdf5_add_scalar_attr(octave_hdf5_id loc_id, octave_hdf5_id type_id, const char *attr_name, void *buf)
Definition: ls-hdf5.cc:1207
bool add_hdf5_data(octave_hdf5_id loc_id, const octave_value &tc, const std::string &name, const std::string &doc, bool mark_global, bool save_as_floats)
Definition: ls-hdf5.cc:1407
static std::string make_valid_identifier(const std::string &nm)
Definition: ls-hdf5.cc:242
static hid_t check_hdf5_id_value(octave_hdf5_id id, const char *who)
Definition: ls-hdf5.cc:79
bool hdf5_check_attr(octave_hdf5_id loc_id, const char *attr_name)
Definition: ls-hdf5.cc:300
std::string tempnam(const std::string &dir, const std::string &pfx)
Definition: file-ops.cc:641
std::string canonicalize_file_name(const std::string &name)
Definition: file-ops.cc:688
int rename(const std::string &from, const std::string &to)
Definition: file-ops.cc:503
std::string get_ASCII_filename(const std::string &orig_file_name, const bool allow_locale)
Definition: lo-sysdep.cc:581
octave_value lookup_type(const std::string &nm)
Definition: ov-typeinfo.cc:776
interpreter & __get_interpreter__(const std::string &who)
type_info & __get_type_info__(const std::string &who)
OCTAVE_NAMESPACE_BEGIN bool check_hdf5_types(bool warn)
int octave_hdf5_err
int64_t octave_hdf5_id
#define H5T_NATIVE_IDX
Definition: oct-hdf5.h:42
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44
OCTAVE_NAMESPACE_BEGIN bool valid_identifier(const char *s)
Definition: utils.cc:77
F77_RET_T len
Definition: xerbla.cc:61