GNU Octave  8.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-2023 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 # 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 
237  panic_impossible ();
238 #endif
239 }
240 
241 static std::string
242 make_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 
268 bool
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 
299 bool
300 hdf5_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_fcn;
311  void *err_fcn_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_fcn, &err_fcn_data);
318  H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr);
319 #else
320  H5Eget_auto (&err_fcn, &err_fcn_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_fcn, err_fcn_data);
336 #else
337  H5Eset_auto (err_fcn, err_fcn_data);
338 #endif
339  return retval;
340 
341 #else
342  err_disabled_feature ("hdf5_check_attr", "HDF5");
343 #endif
344 }
345 
346 bool
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_fcn;
359  void *err_fcn_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_fcn, &err_fcn_data);
366  H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr);
367 #else
368  H5Eget_auto (&err_fcn, &err_fcn_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_fcn, err_fcn_data);
388 #else
389  H5Eset_auto (err_fcn, err_fcn_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 
429 static hid_t
430 hdf5_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 
441 static herr_t
442 load_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 = octave::__get_interpreter__ ();
626 
627  octave_value_list tmp = interp.feval ("inline", args, 1);
628 
629  if (tmp.length () > 0)
630  {
631  retval = tmp(0);
632  return 1;
633  }
634 
635 #else
636  octave_unused_parameter (loc_id);
637  octave_unused_parameter (name);
638  octave_unused_parameter (retval);
639 
640  warn_load ("hdf5");
641 #endif
642 
643  return -1;
644 }
645 
646 // This function is designed to be passed to H5Giterate, which calls it
647 // on each data item in an HDF5 file. For the item whose name is NAME in
648 // the group GROUP_ID, this function sets dv->tc to an Octave representation
649 // of that item. (dv must be a pointer to hdf5_callback_data.) (It also
650 // sets the other fields of dv).
651 //
652 // It returns 1 on success (in which case H5Giterate stops and returns),
653 // -1 on error, and 0 to tell H5Giterate to continue on to the next item
654 // (e.g., if NAME was a data type we don't recognize).
655 //
656 // This function must not throw an exception.
657 
658 static herr_t
659 hdf5_read_next_data_internal (hid_t group_id, const char *name, void *dv)
660 {
661  hdf5_callback_data *d = static_cast<hdf5_callback_data *> (dv);
662  hid_t type_id = -1;
663  hid_t type_class_id = -1;
664  hid_t data_id = -1;
665  hid_t subgroup_id = -1;
666  hid_t space_id = -1;;
667 
668  H5G_stat_t info;
669  herr_t retval = 0;
670  bool ident_valid = octave::valid_identifier (name);
671 
672  std::string vname = name;
673 
674  octave::type_info& type_info = octave::__get_type_info__ ();
675 
676  // Allow identifiers as all digits so we can load lists saved by
677  // earlier versions of Octave.
678 
679  if (! ident_valid)
680  {
681  // fix the identifier, replacing invalid chars with underscores
682  vname = make_valid_identifier (vname);
683 
684  // check again (in case vname was null, empty, or some such thing):
685  ident_valid = octave::valid_identifier (vname);
686  }
687 
688  H5Gget_objinfo (group_id, name, 1, &info);
689 
690  if (info.type == H5G_GROUP && ident_valid)
691  {
692 #if defined (HAVE_HDF5_18)
693  subgroup_id = H5Gopen (group_id, name, octave_H5P_DEFAULT);
694 #else
695  subgroup_id = H5Gopen (group_id, name);
696 #endif
697 
698  if (subgroup_id < 0)
699  {
700  retval = subgroup_id;
701  goto done;
702  }
703 
704  if (hdf5_check_attr (subgroup_id, "OCTAVE_NEW_FORMAT"))
705  {
706 #if defined (HAVE_HDF5_18)
707  data_id = H5Dopen (subgroup_id, "type", octave_H5P_DEFAULT);
708 #else
709  data_id = H5Dopen (subgroup_id, "type");
710 #endif
711 
712  if (data_id < 0)
713  {
714  retval = data_id;
715  goto done;
716  }
717 
718  type_id = H5Dget_type (data_id);
719 
720  type_class_id = H5Tget_class (type_id);
721 
722  if (type_class_id != H5T_STRING)
723  goto done;
724 
725  space_id = H5Dget_space (data_id);
726  hsize_t rank = H5Sget_simple_extent_ndims (space_id);
727 
728  if (rank != 0)
729  goto done;
730 
731  int slen = H5Tget_size (type_id);
732  if (slen < 0)
733  goto done;
734 
735  OCTAVE_LOCAL_BUFFER (char, typ, slen);
736 
737  // create datatype for (null-terminated) string to read into:
738  hid_t st_id = H5Tcopy (H5T_C_S1);
739  H5Tset_size (st_id, slen);
740 
741  if (H5Dread (data_id, st_id, octave_H5S_ALL, octave_H5S_ALL,
742  octave_H5P_DEFAULT, typ) < 0)
743  goto done;
744 
745  H5Tclose (st_id);
746  H5Dclose (data_id);
747 
748  if (std::string (typ, slen-1) == "inline function")
749  {
750  retval = load_inline_fcn (subgroup_id, name, d->tc);
751  }
752  else
753  {
754  d->tc = type_info.lookup_type (std::string (typ, slen-1));
755 
756  try
757  {
758  retval = (d->tc.load_hdf5 (subgroup_id, "value") ? 1 : -1);
759  }
760  catch (const octave::execution_exception& ee)
761  {
762  retval = -1;
763  }
764  }
765 
766  // check for OCTAVE_GLOBAL attribute:
767  d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
768 
769  H5Gclose (subgroup_id);
770  }
771  else
772  {
773  // It seems that this block only applies to an old list type
774  // and that we shouldn't need to handle the old inline
775  // function type here.
776 
777  // an HDF5 group is treated as an octave structure by
778  // default (since that preserves name information), and an
779  // octave list otherwise.
780 
781  if (hdf5_check_attr (subgroup_id, "OCTAVE_LIST"))
782  d->tc = type_info.lookup_type ("list");
783  else
784  d->tc = type_info.lookup_type ("struct");
785 
786  // check for OCTAVE_GLOBAL attribute:
787  d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
788 
789  H5Gclose (subgroup_id);
790 
791  try
792  {
793  retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
794  }
795  catch (const octave::execution_exception& ee)
796  {
797  retval = -1;
798  }
799  }
800 
801  }
802  else if (info.type == H5G_DATASET && ident_valid)
803  {
804  // It seems that this block only applies to an old version of
805  // Octave HDF5 files and that it is probably not important to
806  // handle the old inline function type here.
807 
808  // For backwards compatibility.
809 #if defined (HAVE_HDF5_18)
810  data_id = H5Dopen (group_id, name, octave_H5P_DEFAULT);
811 #else
812  data_id = H5Dopen (group_id, name);
813 #endif
814 
815  if (data_id < 0)
816  {
817  retval = data_id;
818  goto done;
819  }
820 
821  type_id = H5Dget_type (data_id);
822 
823  type_class_id = H5Tget_class (type_id);
824 
825  if (type_class_id == H5T_FLOAT)
826  {
827  space_id = H5Dget_space (data_id);
828 
829  hsize_t rank = H5Sget_simple_extent_ndims (space_id);
830 
831  if (rank == 0)
832  d->tc = type_info.lookup_type ("scalar");
833  else
834  d->tc = type_info.lookup_type ("matrix");
835 
836  H5Sclose (space_id);
837  }
838  else if (type_class_id == H5T_INTEGER)
839  {
840  // What integer type do we really have..
841  std::string int_typ;
842 #if defined (HAVE_H5T_GET_NATIVE_TYPE)
843  // FIXME: test this code and activated with an autoconf
844  // test!! It is also incorrect for 64-bit indexing!!
845 
846  switch (H5Tget_native_type (type_id, H5T_DIR_ASCEND))
847  {
848  case H5T_NATIVE_CHAR:
849  int_typ = "int8 ";
850  break;
851 
852  case H5T_NATIVE_SHORT:
853  int_typ = "int16 ";
854  break;
855 
856  case H5T_NATIVE_INT:
857  case H5T_NATIVE_LONG:
858  int_typ = "int32 ";
859  break;
860 
861  case H5T_NATIVE_LLONG:
862  int_typ = "int64 ";
863  break;
864 
865  case H5T_NATIVE_UCHAR:
866  int_typ = "uint8 ";
867  break;
868 
869  case H5T_NATIVE_USHORT:
870  int_typ = "uint16 ";
871  break;
872 
873  case H5T_NATIVE_UINT:
874  case H5T_NATIVE_ULONG:
875  int_typ = "uint32 ";
876  break;
877 
878  case H5T_NATIVE_ULLONG:
879  int_typ = "uint64 ";
880  break;
881  }
882 #else
883  hid_t int_sign = H5Tget_sign (type_id);
884 
885  if (int_sign == H5T_SGN_ERROR)
886  warning ("load: can't read '%s' (unknown datatype)", name);
887  else
888  {
889  if (int_sign == H5T_SGN_NONE)
890  int_typ.push_back ('u');
891  int_typ.append ("int");
892 
893  int slen = H5Tget_size (type_id);
894  if (slen < 0)
895  warning ("load: can't read '%s' (unknown datatype)", name);
896  else
897  {
898  switch (slen)
899  {
900  case 1:
901  int_typ.append ("8 ");
902  break;
903 
904  case 2:
905  int_typ.append ("16 ");
906  break;
907 
908  case 4:
909  int_typ.append ("32 ");
910  break;
911 
912  case 8:
913  int_typ.append ("64 ");
914  break;
915 
916  default:
917  warning ("load: can't read '%s' (unknown datatype)",
918  name);
919  int_typ = "";
920  break;
921  }
922  }
923  }
924 #endif
925  if (int_typ == "")
926  warning ("load: can't read '%s' (unknown datatype)", name);
927  else
928  {
929  // Matrix or scalar?
930  space_id = H5Dget_space (data_id);
931 
932  hsize_t rank = H5Sget_simple_extent_ndims (space_id);
933 
934  if (rank == 0)
935  int_typ.append ("scalar");
936  else
937  int_typ.append ("matrix");
938 
939  d->tc = type_info.lookup_type (int_typ);
940  H5Sclose (space_id);
941  }
942  }
943  else if (type_class_id == H5T_STRING)
944  d->tc = type_info.lookup_type ("string");
945  else if (type_class_id == H5T_COMPOUND)
946  {
947  hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
948  hid_t range_type = hdf5_make_range_type (H5T_NATIVE_DOUBLE);
949 
950  if (hdf5_types_compatible (type_id, complex_type))
951  {
952  // read complex matrix or scalar variable
953  space_id = H5Dget_space (data_id);
954  hsize_t rank = H5Sget_simple_extent_ndims (space_id);
955 
956  if (rank == 0)
957  d->tc = type_info.lookup_type ("complex scalar");
958  else
959  d->tc = type_info.lookup_type ("complex matrix");
960 
961  H5Sclose (space_id);
962  }
963  else if (hdf5_types_compatible (type_id, range_type))
964  {
965  // If it's not a complex, check if it's a range
966  d->tc = octave_value_typeinfo::lookup_type ("range");
967  }
968  else // Otherwise, just ignore it with a warning.
969  {
970  warning ("load: can't read '%s' (unknown datatype)", name);
971  retval = 0; // unknown datatype; skip
972  return retval;
973  }
974 
975  H5Tclose (range_type);
976  H5Tclose (complex_type);
977  }
978  else
979  {
980  warning ("load: can't read '%s' (unknown datatype)", name);
981  retval = 0; // unknown datatype; skip
982  return retval;
983  }
984 
985  // check for OCTAVE_GLOBAL attribute:
986  d->global = hdf5_check_attr (data_id, "OCTAVE_GLOBAL");
987 
988  try
989  {
990  retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
991  }
992  catch (const octave::execution_exception& ee)
993  {
994  retval = -1;
995  }
996 
997  H5Tclose (type_id);
998  H5Dclose (data_id);
999  }
1000 
1001  if (! ident_valid)
1002  {
1003  // should we attempt to handle invalid identifiers by converting
1004  // bad characters to '_', say?
1005  warning ("load: skipping invalid identifier '%s' in hdf5 file",
1006  name);
1007  }
1008 
1009 done:
1010  if (retval < 0)
1011  {
1012  // Must be warning. A call to error aborts and leaves H5Giterate in
1013  // a mangled state that causes segfault on exit (bug #56149).
1014  warning ("load: error while reading hdf5 item '%s'", name);
1015  }
1016 
1017  if (retval > 0)
1018  {
1019  // get documentation string, if any:
1020  int comment_length = H5Gget_comment (group_id, name, 0, nullptr);
1021 
1022  if (comment_length > 1)
1023  {
1024  OCTAVE_LOCAL_BUFFER (char, tdoc, comment_length);
1025  H5Gget_comment (group_id, name, comment_length, tdoc);
1026  d->doc = tdoc;
1027  }
1028  else if (vname != name)
1029  {
1030  // the name was changed; store the original name
1031  // as the documentation string:
1032  d->doc = name;
1033  }
1034 
1035  // copy name (actually, vname):
1036  d->name = vname;
1037  }
1038 
1039  return retval;
1040 }
1041 
1042 #endif
1043 
1045 hdf5_read_next_data (octave_hdf5_id group_id, const char *name, void *dv)
1046 {
1047 #if defined (HAVE_HDF5)
1048 
1049  hid_t new_id = check_hdf5_id_value (group_id, "hdf5_read_next_data");
1050 
1051  return hdf5_read_next_data_internal (new_id, name, dv);
1052 
1053 #else
1054  err_disabled_feature ("hdf5_read_next_data", "HDF5");
1055 #endif
1056 }
1057 
1059 hdf5_h5g_iterate (octave_hdf5_id loc_id, const char *name, int *idx,
1060  void *operator_data)
1061 {
1062 #if defined (HAVE_HDF5)
1063 
1064  hid_t new_id = check_hdf5_id_value (loc_id, "hdf5_h5g_iterate");
1065 
1066  return H5Giterate (new_id, name, idx, hdf5_read_next_data_internal,
1067  operator_data);
1068 
1069 #else
1070  err_disabled_feature ("hdf5_h5g_iterate", "HDF5");
1071 #endif
1072 }
1073 
1074 // Read the next Octave variable from the stream IS, which must really be an
1075 // hdf5_ifstream. Return the variable value in tc, its docstring in doc, and
1076 // whether it is global in global. The return value is the name of the
1077 // variable, or NULL if none were found or there was an error.
1078 std::string
1079 read_hdf5_data (std::istream& is, const std::string& /* filename */,
1080  bool& global, octave_value& tc, std::string& doc,
1081  const string_vector& argv, int argv_idx, int argc)
1082 {
1083 #if defined (HAVE_HDF5)
1084 
1086 
1087  std::string retval;
1088 
1089  doc.clear ();
1090 
1091  hdf5_ifstream& hs = dynamic_cast<hdf5_ifstream&> (is);
1093 
1094  herr_t H5Giterate_retval = -1;
1095 
1096  hsize_t num_obj = 0;
1097 #if defined (HAVE_HDF5_18)
1098  hid_t group_id = H5Gopen (hs.file_id, "/", octave_H5P_DEFAULT);
1099 #else
1100  hid_t group_id = H5Gopen (hs.file_id, "/");
1101 #endif
1102  H5Gget_num_objs (group_id, &num_obj);
1103  H5Gclose (group_id);
1104 
1105  // For large datasets and out-of-core functionality,
1106  // check if only parts of the data is requested
1107  bool load_named_vars = argv_idx < argc;
1108  while (load_named_vars && hs.current_item < static_cast<int> (num_obj))
1109  {
1110  std::vector<char> var_name;
1111  bool found = false;
1112  std::size_t len = 0;
1113 
1114  len = H5Gget_objname_by_idx (hs.file_id, hs.current_item, nullptr, 0);
1115  var_name.resize (len+1);
1116  H5Gget_objname_by_idx (hs.file_id, hs.current_item, &var_name[0], len+1);
1117 
1118  for (int i = argv_idx; i < argc; i++)
1119  {
1120  glob_match pattern (argv[i]);
1121  if (pattern.match (std::string (&var_name[0])))
1122  {
1123  found = true;
1124  break;
1125  }
1126  }
1127 
1128  if (found)
1129  break;
1130 
1131  hs.current_item++;
1132  }
1133 
1134  if (hs.current_item < static_cast<int> (num_obj))
1135  H5Giterate_retval = H5Giterate (hs.file_id, "/", &hs.current_item,
1137 
1138  if (H5Giterate_retval > 0)
1139  {
1140  global = d.global;
1141  tc = d.tc;
1142  doc = d.doc;
1143  }
1144  else
1145  {
1146  // An error occurred (H5Giterate_retval < 0),
1147  // or there are no more datasets (H5Giterate_retval == 0).
1148  // hdf5_read_next_data_internal has already printed a warning msg.
1149  }
1150 
1151  if (! d.name.empty ())
1152  retval = d.name;
1153 
1154  return retval;
1155 
1156 #else
1157  err_disabled_feature ("read_hdf5_data", "HDF5");
1158 #endif
1159 }
1160 
1161 // Add an attribute named attr_name to loc_id (a simple scalar
1162 // attribute with value 1). Return value is >= 0 on success.
1164 hdf5_add_attr (octave_hdf5_id loc_id, const char *attr_name)
1165 {
1166 #if defined (HAVE_HDF5)
1167 
1168  herr_t retval = 0;
1169 
1170  hid_t as_id = H5Screate (H5S_SCALAR);
1171 
1172  if (as_id >= 0)
1173  {
1174 #if defined (HAVE_HDF5_18)
1175  hid_t a_id = H5Acreate (loc_id, attr_name, H5T_NATIVE_UCHAR,
1177 #else
1178  hid_t a_id = H5Acreate (loc_id, attr_name,
1179  H5T_NATIVE_UCHAR, as_id, octave_H5P_DEFAULT);
1180 #endif
1181  if (a_id >= 0)
1182  {
1183  unsigned char attr_val = 1;
1184 
1185  retval = H5Awrite (a_id, H5T_NATIVE_UCHAR, &attr_val);
1186 
1187  H5Aclose (a_id);
1188  }
1189  else
1190  retval = a_id;
1191 
1192  H5Sclose (as_id);
1193  }
1194  else
1195  retval = as_id;
1196 
1197  return retval;
1198 
1199 #else
1200  err_disabled_feature ("hdf5_add_attr", "HDF5");
1201 #endif
1202 }
1203 
1206  const char *attr_name, void *buf)
1207 {
1208 #if defined (HAVE_HDF5)
1209 
1210  herr_t retval = 0;
1211 
1212  hid_t as_id = H5Screate (H5S_SCALAR);
1213 
1214  if (as_id >= 0)
1215  {
1216 #if defined (HAVE_HDF5_18)
1217  hid_t a_id = H5Acreate (loc_id, attr_name, type_id,
1219 #else
1220  hid_t a_id = H5Acreate (loc_id, attr_name,
1221  type_id, as_id, octave_H5P_DEFAULT);
1222 #endif
1223  if (a_id >= 0)
1224  {
1225  retval = H5Awrite (a_id, type_id, buf);
1226 
1227  H5Aclose (a_id);
1228  }
1229  else
1230  retval = a_id;
1231 
1232  H5Sclose (as_id);
1233  }
1234  else
1235  retval = as_id;
1236 
1237  return retval;
1238 
1239 #else
1240  err_disabled_feature ("hdf5_add_scalar_attr", "HDF5");
1241 #endif
1242 }
1243 
1244 // Save an empty matrix, if needed. Returns
1245 // > 0 Saved empty matrix
1246 // = 0 Not an empty matrix; did nothing
1247 // < 0 Error condition
1248 int
1249 save_hdf5_empty (octave_hdf5_id loc_id, const char *name, const dim_vector& d)
1250 {
1251 #if defined (HAVE_HDF5)
1252 
1253  hsize_t sz = d.length ();
1255  bool empty = false;
1256  hid_t space_hid = -1;
1257  hid_t data_hid = -1;
1258  int retval;
1259  for (hsize_t i = 0; i < sz; i++)
1260  {
1261  dims[i] = d(i);
1262  if (dims[i] < 1)
1263  empty = true;
1264  }
1265 
1266  if (! empty)
1267  return 0;
1268 
1269  space_hid = H5Screate_simple (1, &sz, nullptr);
1270  if (space_hid < 0) return space_hid;
1271 #if defined (HAVE_HDF5_18)
1272  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,
1275 #else
1276  data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid,
1278 #endif
1279  if (data_hid < 0)
1280  {
1281  H5Sclose (space_hid);
1282  return data_hid;
1283  }
1284 
1285  retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
1286  octave_H5P_DEFAULT, dims) >= 0;
1287 
1288  H5Dclose (data_hid);
1289  H5Sclose (space_hid);
1290 
1291  if (retval)
1292  retval = hdf5_add_attr (loc_id, "OCTAVE_EMPTY_MATRIX");
1293 
1294  return (retval == 0 ? 1 : retval);
1295 
1296 #else
1297  err_disabled_feature ("save_hdf5_empty", "HDF5");
1298 #endif
1299 }
1300 
1301 // Load an empty matrix, if needed. Returns
1302 // > 0 loaded empty matrix, dimensions returned
1303 // = 0 Not an empty matrix; did nothing
1304 // < 0 Error condition
1305 int
1306 load_hdf5_empty (octave_hdf5_id loc_id, const char *name, dim_vector& d)
1307 {
1308 #if defined (HAVE_HDF5)
1309 
1310  if (! hdf5_check_attr (loc_id, "OCTAVE_EMPTY_MATRIX"))
1311  return 0;
1312 
1313  hsize_t hdims, maxdims;
1314 #if defined (HAVE_HDF5_18)
1315  hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT);
1316 #else
1317  hid_t data_hid = H5Dopen (loc_id, name);
1318 #endif
1319  hid_t space_id = H5Dget_space (data_hid);
1320  H5Sget_simple_extent_dims (space_id, &hdims, &maxdims);
1321  int retval;
1322 
1323  OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, hdims);
1324 
1325  retval = H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL,
1326  octave_H5P_DEFAULT, dims);
1327  if (retval >= 0)
1328  {
1329  d.resize (hdims);
1330  for (hsize_t i = 0; i < hdims; i++)
1331  d(i) = dims[i];
1332  }
1333 
1334  H5Sclose (space_id);
1335  H5Dclose (data_hid);
1336 
1337  return (retval == 0 ? hdims : retval);
1338 
1339 #else
1340  err_disabled_feature ("load_hdf5_empty", "HDF5");
1341 #endif
1342 }
1343 
1344 // save_type_to_hdf5 is not currently used, since hdf5 doesn't yet support
1345 // automatic float<->integer conversions:
1346 
1347 // return the HDF5 type id corresponding to the Octave save_type
1348 
1351 {
1352 #if defined (HAVE_HDF5)
1353 # if defined (HAVE_HDF5_INT2FLOAT_CONVERSIONS)
1354 
1355  switch (st)
1356  {
1357  case LS_U_CHAR:
1358  return H5T_NATIVE_UCHAR;
1359 
1360  case LS_U_SHORT:
1361  return H5T_NATIVE_USHORT;
1362 
1363  case LS_U_INT:
1364  return H5T_NATIVE_UINT;
1365 
1366  case LS_CHAR:
1367  return H5T_NATIVE_CHAR;
1368 
1369  case LS_SHORT:
1370  return H5T_NATIVE_SHORT;
1371 
1372  case LS_INT:
1373  return H5T_NATIVE_INT;
1374 
1375  case LS_FLOAT:
1376  return H5T_NATIVE_FLOAT;
1377 
1378  case LS_DOUBLE:
1379  default:
1380  return H5T_NATIVE_DOUBLE;
1381  }
1382 
1383 # else
1384 
1385  octave_unused_parameter (st);
1386 
1387  return -1;
1388 
1389 # endif
1390 
1391 #else
1392 
1393  octave_unused_parameter (st);
1394 
1395  err_disabled_feature ("save_type_to_hdf5", "HDF5");
1396 
1397 #endif
1398 }
1399 
1400 // Add the data from TC to the HDF5 location loc_id, which could
1401 // be either a file or a group within a file. Return true if
1402 // successful. This function calls itself recursively for lists
1403 // (stored as HDF5 groups).
1404 
1405 bool
1407  const std::string& name, const std::string& doc,
1408  bool mark_global, bool save_as_floats)
1409 {
1410 #if defined (HAVE_HDF5)
1411 
1412  hsize_t dims[3];
1413  hid_t type_id, space_id, data_id, data_type_id;
1414  type_id = space_id = data_id = data_type_id = -1;
1415 
1416  bool retval = false;
1417  octave_value val = tc;
1418  // FIXME: diagonal & permutation matrices currently don't know how to save
1419  // themselves, so we convert them first to normal matrices using A = A(:,:).
1420  // This is a temporary hack.
1421  if (val.is_diag_matrix () || val.is_perm_matrix ()
1423  val = val.full_value ();
1424 
1425  std::string t = val.type_name ();
1426 #if defined (HAVE_HDF5_18)
1427  data_id = H5Gcreate (loc_id, name.c_str (), octave_H5P_DEFAULT,
1429 #else
1430  data_id = H5Gcreate (loc_id, name.c_str (), 0);
1431 #endif
1432  if (data_id < 0)
1433  goto error_cleanup;
1434 
1435  // attach the type of the variable
1436  type_id = H5Tcopy (H5T_C_S1); H5Tset_size (type_id, t.length () + 1);
1437  if (type_id < 0)
1438  goto error_cleanup;
1439 
1440  dims[0] = 0;
1441  space_id = H5Screate_simple (0, dims, nullptr);
1442  if (space_id < 0)
1443  goto error_cleanup;
1444 #if defined (HAVE_HDF5_18)
1445  data_type_id = H5Dcreate (data_id, "type", type_id, space_id,
1448 #else
1449  data_type_id = H5Dcreate (data_id, "type", type_id, space_id,
1451 #endif
1452  if (data_type_id < 0
1453  || H5Dwrite (data_type_id, type_id, octave_H5S_ALL, octave_H5S_ALL,
1454  octave_H5P_DEFAULT, t.c_str ()) < 0)
1455  goto error_cleanup;
1456 
1457  // Now call the real function to save the variable
1458  retval = val.save_hdf5 (data_id, "value", save_as_floats);
1459 
1460  // attach doc string as comment:
1461  if (retval && doc.length () > 0
1462  && H5Gset_comment (loc_id, name.c_str (), doc.c_str ()) < 0)
1463  retval = false;
1464 
1465  // if it's global, add an attribute "OCTAVE_GLOBAL" with value 1
1466  if (retval && mark_global)
1467  retval = hdf5_add_attr (data_id, "OCTAVE_GLOBAL") >= 0;
1468 
1469  // We are saving in the new variable format, so mark it
1470  if (retval)
1471  retval = hdf5_add_attr (data_id, "OCTAVE_NEW_FORMAT") >= 0;
1472 
1473 error_cleanup:
1474 
1475  if (data_type_id >= 0)
1476  H5Dclose (data_type_id);
1477 
1478  if (type_id >= 0)
1479  H5Tclose (type_id);
1480 
1481  if (space_id >= 0)
1482  H5Sclose (space_id);
1483 
1484  if (data_id >= 0)
1485  H5Gclose (data_id);
1486 
1487  if (! retval)
1488  error ("save: error while writing '%s' to hdf5 file", name.c_str ());
1489 
1490  return retval;
1491 
1492 #else
1493  err_disabled_feature ("add_hdf5_data", "HDF5");
1494 #endif
1495 }
1496 
1497 // Write data from TC in HDF5 (binary) format to the stream OS,
1498 // which must be an hdf5_ofstream, returning true on success.
1499 
1500 bool
1501 save_hdf5_data (std::ostream& os, const octave_value& tc,
1502  const std::string& name, const std::string& doc,
1503  bool mark_global, bool save_as_floats)
1504 {
1505 #if defined (HAVE_HDF5)
1506 
1508 
1509  hdf5_ofstream& hs = dynamic_cast<hdf5_ofstream&> (os);
1510 
1511  return add_hdf5_data (hs.file_id, tc, name, doc,
1512  mark_global, save_as_floats);
1513 
1514 #else
1515  err_disabled_feature ("save_hdf5_data", "HDF5");
1516 #endif
1517 }
1518 
1519 #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:280
octave_idx_type length(void) const
Definition: ovl.h:113
int type_id(void) const
Definition: ov.h:1450
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
Definition: ov.h:1500
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:1452
octave_value lookup_type(const std::string &nm)
Definition: ov-typeinfo.cc:481
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:1054
void error(const char *fmt,...)
Definition: error.cc:979
#define panic_impossible()
Definition: error.h:508
void err_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition: errwarn.cc:53
int rename(const std::string &from, const std::string &to)
Definition: file-ops.cc:559
std::string canonicalize_file_name(const std::string &name)
Definition: file-ops.cc:744
std::string tempnam(const std::string &dir, const std::string &pfx)
Definition: file-ops.cc:697
interpreter & __get_interpreter__(void)
type_info & __get_type_info__(void)
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
std::string get_ASCII_filename(const std::string &orig_file_name, const bool allow_locale)
Definition: lo-sysdep.cc:605
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:1501
static herr_t hdf5_read_next_data_internal(hid_t group_id, const char *name, void *dv)
Definition: ls-hdf5.cc:659
int save_hdf5_empty(octave_hdf5_id loc_id, const char *name, const dim_vector &d)
Definition: ls-hdf5.cc:1249
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:1079
octave_hdf5_err hdf5_add_attr(octave_hdf5_id loc_id, const char *attr_name)
Definition: ls-hdf5.cc:1164
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:1306
octave_hdf5_id save_type_to_hdf5(save_type st)
Definition: ls-hdf5.cc:1350
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:1045
octave_hdf5_err hdf5_h5g_iterate(octave_hdf5_id loc_id, const char *name, int *idx, void *operator_data)
Definition: ls-hdf5.cc:1059
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:1205
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:1406
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
octave_idx_type n
Definition: mx-inlines.cc:753
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 lookup_type(const std::string &nm)
Definition: ov-typeinfo.cc:779
bool valid_identifier(const char *s)
Definition: utils.cc:78
F77_RET_T len
Definition: xerbla.cc:61