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