Mercurial > octave
view libinterp/corefcn/ls-hdf5.cc @ 31771:21f9b34eb893
maint: Eliminate "(void)" in C++ function prototypes/declarations.
* mk-opts.pl, external.txi, embedded.cc, make_int.cc, standalone.cc,
standalonebuiltin.cc, BaseControl.cc, BaseControl.h, ButtonControl.cc,
ButtonControl.h, ButtonGroup.cc, ButtonGroup.h, Canvas.cc, Canvas.h,
CheckBoxControl.cc, CheckBoxControl.h, Container.cc, Container.h,
ContextMenu.cc, ContextMenu.h, EditControl.cc, EditControl.h, Figure.cc,
Figure.h, FigureWindow.cc, FigureWindow.h, GLCanvas.cc, GLCanvas.h,
GenericEventNotify.h, KeyMap.cc, ListBoxControl.cc, ListBoxControl.h,
Logger.cc, Logger.h, Menu.cc, Menu.h, MenuContainer.h, Object.cc, Object.h,
ObjectProxy.cc, ObjectProxy.h, Panel.cc, Panel.h, PopupMenuControl.cc,
PopupMenuControl.h, PushButtonControl.cc, PushButtonControl.h, PushTool.cc,
PushTool.h, RadioButtonControl.cc, RadioButtonControl.h, SliderControl.cc,
SliderControl.h, Table.cc, Table.h, TextControl.cc, TextControl.h, TextEdit.h,
ToggleButtonControl.cc, ToggleButtonControl.h, ToggleTool.cc, ToggleTool.h,
ToolBar.cc, ToolBar.h, ToolBarButton.cc, ToolBarButton.h, gl-select.cc,
gl-select.h, qopengl-functions.h, qt-graphics-toolkit.h, qdialog.cpp,
qfontdialog.cpp, qprintdialog_win.cpp, liboctgui-build-info.h,
liboctgui-build-info.in.cc, color-picker.cc, color-picker.h, command-widget.cc,
command-widget.h, community-news.cc, community-news.h, dialog.cc, dialog.h,
documentation-bookmarks.cc, documentation-bookmarks.h,
documentation-dock-widget.cc, documentation-dock-widget.h, documentation.cc,
documentation.h, dw-main-window.cc, dw-main-window.h,
external-editor-interface.cc, external-editor-interface.h,
files-dock-widget.cc, files-dock-widget.h, find-files-dialog.cc,
find-files-dialog.h, find-files-model.cc, find-files-model.h,
gui-preferences.cc, gui-preferences.h, gui-settings.cc, gui-settings.h,
history-dock-widget.cc, history-dock-widget.h, interpreter-qobject.cc,
interpreter-qobject.h, file-editor-interface.h, file-editor-tab.cc,
file-editor-tab.h, file-editor.cc, file-editor.h, find-dialog.cc,
find-dialog.h, marker.cc, marker.h, octave-qscintilla.cc, octave-qscintilla.h,
octave-txt-lexer.cc, octave-txt-lexer.h, main-window.cc, main-window.h,
news-reader.cc, news-reader.h, octave-dock-widget.cc, octave-dock-widget.h,
octave-qobject.cc, octave-qobject.h, qt-application.cc, qt-application.h,
qt-interpreter-events.cc, qt-interpreter-events.h, release-notes.cc,
release-notes.h, set-path-dialog.cc, set-path-dialog.h, set-path-model.cc,
set-path-model.h, settings-dialog.cc, settings-dialog.h,
shortcuts-tree-widget.cc, shortcuts-tree-widget.h, tab-bar.cc, tab-bar.h,
terminal-dock-widget.cc, terminal-dock-widget.h, variable-editor-model.cc,
variable-editor-model.h, variable-editor.cc, variable-editor.h,
welcome-wizard.cc, welcome-wizard.h, workspace-model.cc, workspace-model.h,
workspace-view.cc, workspace-view.h, build-env.h, Cell.cc, Cell.h,
__contourc__.cc, __magick_read__.cc, auto-shlib.cc, auto-shlib.h,
base-text-renderer.h, bsxfun.cc, c-file-ptr-stream.cc, c-file-ptr-stream.h,
call-stack.cc, call-stack.h, debug.cc, defaults.cc, defaults.h, defun.cc,
display.cc, display.h, dynamic-ld.cc, dynamic-ld.h, environment.cc,
environment.h, error.cc, error.h, errwarn.cc, errwarn.h, event-manager.cc,
event-manager.h, event-queue.cc, event-queue.h, fcn-info.cc, fcn-info.h,
ft-text-renderer.cc, ft-text-renderer.h, genprops.awk, gh-manager.cc,
gh-manager.h, gl-render.cc, gl-render.h, gl2ps-print.cc, graphics-toolkit.h,
graphics.cc, graphics.in.h, gtk-manager.cc, gtk-manager.h, help.cc, help.h,
hook-fcn.h, input.cc, input.h, interpreter-private.cc, interpreter-private.h,
interpreter.cc, interpreter.h, jsondecode.cc, latex-text-renderer.cc,
latex-text-renderer.h, load-path.cc, load-path.h, load-save.cc, load-save.h,
ls-hdf5.cc, ls-hdf5.h, mxarray.h, oct-errno.h, oct-errno.in.cc, oct-fstrm.cc,
oct-fstrm.h, oct-handle.h, oct-hist.cc, oct-hist.h, oct-iostrm.cc,
oct-iostrm.h, oct-map.cc, oct-map.h, oct-opengl.h, oct-prcstrm.cc,
oct-prcstrm.h, oct-procbuf.cc, oct-procbuf.h, oct-process.h, oct-stdstrm.h,
oct-stream.cc, oct-stream.h, oct-strstrm.cc, oct-strstrm.h,
oct-tex-lexer.in.ll, pager.cc, pager.h, pr-flt-fmt.cc, pr-flt-fmt.h,
pr-output.cc, pr-output.h, procstream.cc, procstream.h, settings.cc,
settings.h, sighandlers.cc, sighandlers.h, stack-frame.cc, stack-frame.h,
svd.cc, syminfo.cc, syminfo.h, symrec.cc, symrec.h, symscope.cc, symscope.h,
symtab.cc, symtab.h, sysdep.cc, sysdep.h, text-engine.cc, text-engine.h,
text-renderer.cc, text-renderer.h, toplev.cc, url-handle-manager.cc,
url-handle-manager.h, variables.cc, xpow.cc, __init_fltk__.cc,
__init_gnuplot__.cc, __ode15__.cc, audiodevinfo.cc, gzip.cc,
liboctinterp-build-info.h, liboctinterp-build-info.in.cc,
mk-build-env-features.sh, mk-builtins.pl, cdef-class.cc, cdef-class.h,
cdef-manager.h, cdef-method.cc, cdef-method.h, cdef-object.cc, cdef-object.h,
cdef-package.cc, cdef-package.h, cdef-property.cc, cdef-property.h,
cdef-utils.cc, cdef-utils.h, ov-base-diag.cc, ov-base-diag.h, ov-base-int.cc,
ov-base-int.h, ov-base-mat.cc, ov-base-mat.h, ov-base-scalar.cc,
ov-base-scalar.h, ov-base-sparse.cc, ov-base-sparse.h, ov-base.cc, ov-base.h,
ov-bool-mat.cc, ov-bool-mat.h, ov-bool-sparse.cc, ov-bool-sparse.h, ov-bool.cc,
ov-bool.h, ov-builtin.cc, ov-builtin.h, ov-cell.cc, ov-cell.h, ov-ch-mat.cc,
ov-ch-mat.h, ov-class.cc, ov-class.h, ov-classdef.cc, ov-classdef.h,
ov-colon.h, ov-complex.cc, ov-complex.h, ov-cs-list.h, ov-cx-diag.cc,
ov-cx-diag.h, ov-cx-mat.cc, ov-cx-mat.h, ov-cx-sparse.cc, ov-cx-sparse.h,
ov-dld-fcn.cc, ov-dld-fcn.h, ov-fcn-handle.cc, ov-fcn-handle.h, ov-fcn.cc,
ov-fcn.h, ov-float.cc, ov-float.h, ov-flt-complex.cc, ov-flt-complex.h,
ov-flt-cx-diag.cc, ov-flt-cx-diag.h, ov-flt-cx-mat.cc, ov-flt-cx-mat.h,
ov-flt-re-diag.cc, ov-flt-re-diag.h, ov-flt-re-mat.cc, ov-flt-re-mat.h,
ov-intx.h, ov-java.cc, ov-java.h, ov-lazy-idx.cc, ov-lazy-idx.h,
ov-legacy-range.cc, ov-legacy-range.h, ov-magic-int.cc, ov-magic-int.h,
ov-mex-fcn.cc, ov-mex-fcn.h, ov-null-mat.cc, ov-null-mat.h, ov-oncleanup.cc,
ov-oncleanup.h, ov-perm.cc, ov-perm.h, ov-range.cc, ov-range.h, ov-re-diag.cc,
ov-re-diag.h, ov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc, ov-re-sparse.h,
ov-scalar.cc, ov-scalar.h, ov-str-mat.cc, ov-str-mat.h, ov-struct.cc,
ov-struct.h, ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc, ov-usr-fcn.h, ov.cc,
ov.h, ovl.cc, ovl.h, octave.cc, octave.h, anon-fcn-validator.h, bp-table.cc,
bp-table.h, comment-list.cc, comment-list.h, filepos.h, lex.h, lex.ll,
oct-lvalue.cc, oct-lvalue.h, oct-parse.yy, parse.h, profiler.cc, profiler.h,
pt-anon-scopes.h, pt-arg-list.cc, pt-arg-list.h, pt-args-block.cc,
pt-args-block.h, pt-array-list.cc, pt-array-list.h, pt-assign.cc, pt-assign.h,
pt-binop.cc, pt-binop.h, pt-bp.h, pt-cbinop.h, pt-cell.h, pt-check.h,
pt-classdef.cc, pt-classdef.h, pt-cmd.h, pt-colon.h, pt-const.h, pt-decl.cc,
pt-decl.h, pt-eval.cc, pt-eval.h, pt-except.cc, pt-except.h, pt-exp.cc,
pt-exp.h, pt-fcn-handle.cc, pt-fcn-handle.h, pt-id.cc, pt-id.h, pt-idx.cc,
pt-idx.h, pt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.h, pt-misc.cc, pt-misc.h,
pt-pr-code.cc, pt-pr-code.h, pt-select.cc, pt-select.h, pt-spmd.cc, pt-spmd.h,
pt-stmt.cc, pt-stmt.h, pt-tm-const.cc, pt-tm-const.h, pt-unop.cc, pt-unop.h,
pt-walk.h, pt.cc, pt.h, token.cc, token.h, usage.h, Array-base.cc, Array.h,
CColVector.cc, CColVector.h, CDiagMatrix.cc, CDiagMatrix.h, CMatrix.cc,
CMatrix.h, CNDArray.cc, CNDArray.h, CRowVector.cc, CRowVector.h, CSparse.cc,
CSparse.h, DiagArray2.cc, DiagArray2.h, MArray.cc, MArray.h, MDiagArray2.h,
MSparse.h, MatrixType.cc, MatrixType.h, PermMatrix.cc, PermMatrix.h, Range.cc,
Range.h, Sparse-b.cc, Sparse.cc, Sparse.h, boolMatrix.cc, boolMatrix.h,
boolNDArray.cc, boolNDArray.h, boolSparse.cc, boolSparse.h, chMatrix.h,
chNDArray.h, dColVector.cc, dColVector.h, dDiagMatrix.cc, dDiagMatrix.h,
dMatrix.cc, dMatrix.h, dNDArray.cc, dNDArray.h, dRowVector.cc, dRowVector.h,
dSparse.cc, dSparse.h, dim-vector.cc, dim-vector.h, fCColVector.cc,
fCColVector.h, fCDiagMatrix.cc, fCDiagMatrix.h, fCMatrix.cc, fCMatrix.h,
fCNDArray.cc, fCNDArray.h, fCRowVector.cc, fCRowVector.h, fColVector.cc,
fColVector.h, fDiagMatrix.cc, fDiagMatrix.h, fMatrix.cc, fMatrix.h,
fNDArray.cc, fNDArray.h, fRowVector.cc, fRowVector.h, idx-vector.cc,
idx-vector.h, intNDArray.cc, intNDArray.h, liboctave-build-info.h,
liboctave-build-info.in.cc, CollocWt.cc, CollocWt.h, DAE.h, DAEFunc.h, DAERT.h,
DAERTFunc.h, DASPK.cc, DASPK.h, DASRT.cc, DASRT.h, DASSL.cc, DASSL.h, DET.h,
EIG.h, LSODE.cc, LSODE.h, ODE.h, ODEFunc.h, ODES.h, ODESFunc.h, Quad.h,
aepbalance.cc, aepbalance.h, base-dae.h, base-de.h, chol.cc, chol.h,
eigs-base.cc, fEIG.h, gepbalance.h, gsvd.cc, gsvd.h, hess.h, lu.cc, lu.h,
oct-fftw.cc, oct-fftw.h, oct-rand.cc, oct-rand.h, oct-spparms.cc,
oct-spparms.h, qr.cc, qr.h, qrp.cc, qrp.h, randmtzig.cc, randmtzig.h, schur.h,
sparse-chol.cc, sparse-chol.h, sparse-lu.cc, sparse-lu.h, sparse-qr.cc,
sparse-qr.h, svd.cc, svd.h, child-list.cc, child-list.h, dir-ops.cc, dir-ops.h,
file-ops.cc, file-ops.h, file-stat.cc, file-stat.h, lo-sysdep.cc, lo-sysdep.h,
lo-sysinfo.cc, lo-sysinfo.h, mach-info.cc, mach-info.h, oct-env.cc, oct-env.h,
oct-group.cc, oct-group.h, oct-password.cc, oct-password.h, oct-syscalls.cc,
oct-syscalls.h, oct-time.cc, oct-time.h, oct-uname.cc, oct-uname.h,
action-container.h, base-list.h, caseless-str.h, cmd-edit.cc, cmd-edit.h,
cmd-hist.cc, cmd-hist.h, data-conv.cc, file-info.h, glob-match.cc,
glob-match.h, kpse.cc, kpse.h, lo-array-errwarn.cc, lo-array-errwarn.h,
lo-hash.cc, lo-hash.h, lo-ieee.cc, lo-ieee.h, lo-regexp.cc, lo-regexp.h,
oct-inttypes.cc, oct-inttypes.h, oct-mutex.cc, oct-mutex.h, oct-refcount.h,
oct-shlib.cc, oct-shlib.h, oct-sort.cc, oct-sort.h, oct-sparse.cc,
octave-preserve-stream-state.h, pathsearch.cc, pathsearch.h, quit.cc,
singleton-cleanup.cc, singleton-cleanup.h, str-vec.cc, str-vec.h,
unwind-prot.cc, unwind-prot.h, url-transfer.cc, url-transfer.h, version.cc,
version.in.h, cxx-signal-helpers.cc, acinclude.m4, main-cli.cc, main-gui.cc,
main.in.cc, mkoctfile.in.cc, octave-build-info.h, octave-build-info.in.cc,
octave-config.in.cc, octave-svgconvert.cc, shared-fcns.h:
maint: Eliminate "(void)" in C++ function prototypes/declarations.
author | Rik <rik@octave.org> |
---|---|
date | Tue, 24 Jan 2023 17:19:44 -0800 |
parents | 597f3ee61a48 |
children | c56866c949f0 |
line wrap: on
line source
//////////////////////////////////////////////////////////////////////// // // Copyright (C) 1996-2023 The Octave Project Developers // // See the file COPYRIGHT.md in the top-level directory of this // distribution or <https://octave.org/copyright/>. // // This file is part of Octave. // // Octave is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Octave is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Octave; see the file COPYING. If not, see // <https://www.gnu.org/licenses/>. // //////////////////////////////////////////////////////////////////////// #if defined (HAVE_CONFIG_H) # include "config.h" #endif #if defined (HAVE_HDF5) #include <cctype> #include <iomanip> #include <istream> #include <limits> #include <ostream> #include <string> #include <vector> #include "byte-swap.h" #include "data-conv.h" #include "file-ops.h" #include "glob-match.h" #include "lo-mappers.h" #include "mach-info.h" #include "oct-env.h" #include "oct-time.h" #include "quit.h" #include "str-vec.h" #include "oct-locbuf.h" #include "Cell.h" #include "defun.h" #include "error.h" #include "errwarn.h" #include "interpreter.h" #include "interpreter-private.h" #include "load-save.h" #include "oct-hdf5.h" #include "ovl.h" #include "oct-map.h" #include "ov-cell.h" #include "pager.h" #include "sysdep.h" #include "unwind-prot.h" #include "utils.h" #include "variables.h" #include "version.h" #include "dMatrix.h" #include "ov-lazy-idx.h" #include "ls-utils.h" #include "ls-hdf5.h" #if defined (HAVE_HDF5) static hid_t check_hdf5_id_value (octave_hdf5_id id, const char *who) { if (id > std::numeric_limits<hid_t>::max ()) error ("%s: internal error: ID too large for hid_t", who); return static_cast<hid_t> (id); } #endif hdf5_fstreambase::hdf5_fstreambase (const char *name, int mode, int /* prot */) : file_id (-1), current_item (-1) { #if defined (HAVE_HDF5) open_create (name, mode); current_item = 0; #else err_disabled_feature ("hdf5_fstreambase", "HDF5"); #endif } void hdf5_fstreambase::close () { #if defined (HAVE_HDF5) if (file_id >= 0) { if (H5Fclose (file_id) < 0) std::ios::setstate (std::ios::badbit); file_id = -1; } #else // This shouldn't happen because construction of hdf5_fstreambase // objects is supposed to be impossible if HDF5 is not available. panic_impossible (); #endif } void hdf5_fstreambase::open (const char *name, int mode, int) { #if defined (HAVE_HDF5) clear (); open_create (name, mode); current_item = 0; #else // This shouldn't happen because construction of hdf5_fstreambase // objects is supposed to be impossible if HDF5 is not available. panic_impossible (); #endif } void hdf5_fstreambase::open_create (const char *name, int mode) { #if defined (HAVE_HDF5) // Open the HDF5 file NAME. If it does not exist, create the file. # if defined (HAVE_HDF5_UTF8) const char *fname = name; # else std::string fname_str (name); std::string ascii_fname_str = octave::sys::get_ASCII_filename (fname_str); const char *fname = ascii_fname_str.c_str (); # endif if (mode & std::ios::in) file_id = H5Fopen (fname, H5F_ACC_RDONLY, octave_H5P_DEFAULT); else if (mode & std::ios::out) { if (mode & std::ios::app && H5Fis_hdf5 (fname) > 0) file_id = H5Fopen (fname, H5F_ACC_RDWR, octave_H5P_DEFAULT); else # if defined (HAVE_HDF5_UTF8) file_id = H5Fcreate (fname, H5F_ACC_TRUNC, octave_H5P_DEFAULT, octave_H5P_DEFAULT); # else { // Check whether file already exists std::string abs_ascii_fname = octave::sys::canonicalize_file_name (ascii_fname_str); if (! abs_ascii_fname.empty ()) { // Use the existing file file_id = H5Fcreate (fname, H5F_ACC_TRUNC, octave_H5P_DEFAULT, octave_H5P_DEFAULT); if (file_id < 0) std::ios::setstate (std::ios::badbit); return; } // Check whether filename contains non-ASCII (UTF-8) characters. std::string::const_iterator first_non_ASCII = std::find_if (fname_str.begin (), fname_str.end (), [](char c) { return (c < 0 || c >= 128); }); if (first_non_ASCII == fname_str.end ()) { // No non-ASCII characters file_id = H5Fcreate (name, H5F_ACC_TRUNC, octave_H5P_DEFAULT, octave_H5P_DEFAULT); if (file_id < 0) std::ios::setstate (std::ios::badbit); return; } // Create file in temp folder std::string tmp_name = octave::sys::tempnam ("", "oct-"); octave_hdf5_id hdf5_fid = H5Fcreate (tmp_name.c_str (), H5F_ACC_TRUNC, octave_H5P_DEFAULT, octave_H5P_DEFAULT); if (hdf5_fid < 0) { file_id = -1; std::ios::setstate (std::ios::badbit); return; } // Close file H5Fclose (hdf5_fid); // Move temporary file to final destination std::string msg; int res = octave::sys::rename (tmp_name, name, msg); if (res < 0) { std::ios::setstate (std::ios::badbit); file_id = -1; return; } // Open file at final location ascii_fname_str = octave::sys::get_ASCII_filename (fname_str); ascii_fname = ascii_fname_str.c_str (); file_id = H5Fopen (ascii_fname, H5F_ACC_RDWR, octave_H5P_DEFAULT); } # endif } if (file_id < 0) std::ios::setstate (std::ios::badbit); return; #else // This shouldn't happen because construction of hdf5_fstreambase // objects is supposed to be impossible if HDF5 is not available. panic_impossible (); #endif } static std::string make_valid_identifier (const std::string& nm) { std::string retval; std::size_t nm_len = nm.length (); if (nm_len > 0) { if (! isalpha (nm[0])) retval += '_'; for (std::size_t i = 0; i < nm_len; i++) { char c = nm[i]; retval += (isalnum (c) || c == '_') ? c : '_'; } } return retval; } // Given two compound types t1 and t2, determine whether they // are compatible for reading/writing. This function only // works for non-nested types composed of simple elements (ints, floats...), // which is all we need it for bool hdf5_types_compatible (octave_hdf5_id t1, octave_hdf5_id t2) { #if defined (HAVE_HDF5) int n; if ((n = H5Tget_nmembers (t1)) != H5Tget_nmembers (t2)) return false; for (int i = 0; i < n; ++i) { hid_t mt1 = H5Tget_member_type (t1, i); hid_t mt2 = H5Tget_member_type (t2, i); if (H5Tget_class (mt1) != H5Tget_class (mt2)) return false; H5Tclose (mt2); H5Tclose (mt1); } return true; #else err_disabled_feature ("hdf5_types_compatible", "HDF5"); #endif } // Return true if loc_id has the attribute named attr_name, and false // otherwise. bool hdf5_check_attr (octave_hdf5_id loc_id, const char *attr_name) { #if defined (HAVE_HDF5) bool retval = false; // we have to pull some shenanigans here to make sure // HDF5 doesn't print out all sorts of error messages if we // call H5Aopen for a non-existing attribute H5E_auto_t err_fcn; void *err_fcn_data; // turn off error reporting temporarily, but save the error // reporting function: #if defined (HAVE_HDF5_18) H5Eget_auto (octave_H5E_DEFAULT, &err_fcn, &err_fcn_data); H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr); #else H5Eget_auto (&err_fcn, &err_fcn_data); H5Eset_auto (nullptr, nullptr); #endif hid_t attr_id = H5Aopen_name (loc_id, attr_name); if (attr_id >= 0) { // successful retval = true; H5Aclose (attr_id); } // restore error reporting: #if defined (HAVE_HDF5_18) H5Eset_auto (octave_H5E_DEFAULT, err_fcn, err_fcn_data); #else H5Eset_auto (err_fcn, err_fcn_data); #endif return retval; #else err_disabled_feature ("hdf5_check_attr", "HDF5"); #endif } bool hdf5_get_scalar_attr (octave_hdf5_id loc_id, octave_hdf5_id type_id, const char *attr_name, void *buf) { #if defined (HAVE_HDF5) bool retval = false; // we have to pull some shenanigans here to make sure // HDF5 doesn't print out all sorts of error messages if we // call H5Aopen for a non-existing attribute H5E_auto_t err_fcn; void *err_fcn_data; // turn off error reporting temporarily, but save the error // reporting function: #if defined (HAVE_HDF5_18) H5Eget_auto (octave_H5E_DEFAULT, &err_fcn, &err_fcn_data); H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr); #else H5Eget_auto (&err_fcn, &err_fcn_data); H5Eset_auto (nullptr, nullptr); #endif hid_t attr_id = H5Aopen_name (loc_id, attr_name); if (attr_id >= 0) { hid_t space_id = H5Aget_space (attr_id); hsize_t rank = H5Sget_simple_extent_ndims (space_id); if (rank == 0) retval = H5Aread (attr_id, type_id, buf) >= 0; H5Aclose (attr_id); } // restore error reporting: #if defined (HAVE_HDF5_18) H5Eset_auto (octave_H5E_DEFAULT, err_fcn, err_fcn_data); #else H5Eset_auto (err_fcn, err_fcn_data); #endif return retval; #else err_disabled_feature ("hdf5_get_scalar_attr", "HDF5"); #endif } // The following subroutines creates an HDF5 representations of the way // we will store Octave complex types (pairs of floating-point numbers). // NUM_TYPE is the HDF5 numeric type to use for storage (e.g. // H5T_NATIVE_DOUBLE to save as 'double'). Note that any necessary // conversions are handled automatically by HDF5. octave_hdf5_id hdf5_make_complex_type (octave_hdf5_id num_type) { #if defined (HAVE_HDF5) hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 2); H5Tinsert (type_id, "real", 0 * sizeof (double), num_type); H5Tinsert (type_id, "imag", 1 * sizeof (double), num_type); return type_id; #else err_disabled_feature ("hdf5_make_complex_type", "HDF5"); #endif } #if defined (HAVE_HDF5) // The following subroutine creates an HDF5 representation of the way // we will store Octave range types (triplets of floating-point numbers). // NUM_TYPE is the HDF5 numeric type to use for storage // (e.g., H5T_NATIVE_DOUBLE to save as 'double'). // Note that any necessary conversions are handled automatically by HDF5. static hid_t hdf5_make_range_type (hid_t num_type) { hid_t type_id = H5Tcreate (H5T_COMPOUND, sizeof (double) * 3); H5Tinsert (type_id, "base", 0 * sizeof (double), num_type); H5Tinsert (type_id, "limit", 1 * sizeof (double), num_type); H5Tinsert (type_id, "increment", 2 * sizeof (double), num_type); return type_id; } static herr_t load_inline_fcn (hid_t loc_id, const char *name, octave_value& retval) { #if defined (HAVE_HDF5) hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id; hsize_t rank; int slen; #if defined (HAVE_HDF5_18) group_hid = H5Gopen (loc_id, name, octave_H5P_DEFAULT); #else group_hid = H5Gopen (loc_id, name); #endif if (group_hid < 0) return -1; #if defined (HAVE_HDF5_18) data_hid = H5Dopen (group_hid, "args", octave_H5P_DEFAULT); #else data_hid = H5Dopen (group_hid, "args"); #endif space_hid = H5Dget_space (data_hid); rank = H5Sget_simple_extent_ndims (space_hid); if (rank != 2) { H5Dclose (data_hid); H5Sclose (space_hid); H5Gclose (group_hid); return -1; } OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank); OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank); H5Sget_simple_extent_dims (space_hid, hdims, maxdims); octave_value_list args (hdims[1]+1); OCTAVE_LOCAL_BUFFER (char, s1, hdims[0] * hdims[1]); if (H5Dread (data_hid, H5T_NATIVE_UCHAR, octave_H5S_ALL, octave_H5S_ALL, octave_H5P_DEFAULT, s1) < 0) { H5Dclose (data_hid); H5Sclose (space_hid); H5Gclose (group_hid); return -1; } H5Dclose (data_hid); H5Sclose (space_hid); for (std::size_t i = 0; i < hdims[1]; i++) args(i+1) = std::string (s1 + i*hdims[0]); #if defined (HAVE_HDF5_18) data_hid = H5Dopen (group_hid, "nm", octave_H5P_DEFAULT); #else data_hid = H5Dopen (group_hid, "nm"); #endif if (data_hid < 0) { H5Gclose (group_hid); return -1; } type_hid = H5Dget_type (data_hid); type_class_hid = H5Tget_class (type_hid); if (type_class_hid != H5T_STRING) { H5Tclose (type_hid); H5Dclose (data_hid); H5Gclose (group_hid); return -1; } space_hid = H5Dget_space (data_hid); rank = H5Sget_simple_extent_ndims (space_hid); if (rank != 0) { H5Sclose (space_hid); H5Tclose (type_hid); H5Dclose (data_hid); H5Gclose (group_hid); return -1; } slen = H5Tget_size (type_hid); if (slen < 0) { H5Sclose (space_hid); H5Tclose (type_hid); H5Dclose (data_hid); H5Gclose (group_hid); return -1; } OCTAVE_LOCAL_BUFFER (char, nm_tmp, slen); // create datatype for (null-terminated) string to read into: st_id = H5Tcopy (H5T_C_S1); H5Tset_size (st_id, slen); if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL, octave_H5P_DEFAULT, nm_tmp) < 0) { H5Sclose (space_hid); H5Tclose (type_hid); H5Gclose (group_hid); return -1; } H5Tclose (st_id); H5Dclose (data_hid); // NAME is obsolete and unused. // std::string name (nm_tmp); #if defined (HAVE_HDF5_18) data_hid = H5Dopen (group_hid, "iftext", octave_H5P_DEFAULT); #else data_hid = H5Dopen (group_hid, "iftext"); #endif if (data_hid < 0) { H5Gclose (group_hid); return -1; } type_hid = H5Dget_type (data_hid); type_class_hid = H5Tget_class (type_hid); if (type_class_hid != H5T_STRING) { H5Tclose (type_hid); H5Dclose (data_hid); H5Gclose (group_hid); return -1; } space_hid = H5Dget_space (data_hid); rank = H5Sget_simple_extent_ndims (space_hid); if (rank != 0) { H5Sclose (space_hid); H5Tclose (type_hid); H5Dclose (data_hid); H5Gclose (group_hid); return -1; } slen = H5Tget_size (type_hid); if (slen < 0) { H5Sclose (space_hid); H5Tclose (type_hid); H5Dclose (data_hid); H5Gclose (group_hid); return -1; } OCTAVE_LOCAL_BUFFER (char, iftext_tmp, slen); // create datatype for (null-terminated) string to read into: st_id = H5Tcopy (H5T_C_S1); H5Tset_size (st_id, slen); if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL, octave_H5P_DEFAULT, iftext_tmp) < 0) { H5Sclose (space_hid); H5Tclose (type_hid); H5Gclose (group_hid); return -1; } H5Tclose (st_id); H5Dclose (data_hid); args(0) = std::string (iftext_tmp); octave::interpreter& interp = octave::__get_interpreter__ (); octave_value_list tmp = interp.feval ("inline", args, 1); if (tmp.length () > 0) { retval = tmp(0); return 1; } #else octave_unused_parameter (loc_id); octave_unused_parameter (name); octave_unused_parameter (retval); warn_load ("hdf5"); #endif return -1; } // This function is designed to be passed to H5Giterate, which calls it // on each data item in an HDF5 file. For the item whose name is NAME in // the group GROUP_ID, this function sets dv->tc to an Octave representation // of that item. (dv must be a pointer to hdf5_callback_data.) (It also // sets the other fields of dv). // // It returns 1 on success (in which case H5Giterate stops and returns), // -1 on error, and 0 to tell H5Giterate to continue on to the next item // (e.g., if NAME was a data type we don't recognize). // // This function must not throw an exception. static herr_t hdf5_read_next_data_internal (hid_t group_id, const char *name, void *dv) { hdf5_callback_data *d = static_cast<hdf5_callback_data *> (dv); hid_t type_id = -1; hid_t type_class_id = -1; hid_t data_id = -1; hid_t subgroup_id = -1; hid_t space_id = -1;; H5G_stat_t info; herr_t retval = 0; bool ident_valid = octave::valid_identifier (name); std::string vname = name; octave::type_info& type_info = octave::__get_type_info__ (); // Allow identifiers as all digits so we can load lists saved by // earlier versions of Octave. if (! ident_valid) { // fix the identifier, replacing invalid chars with underscores vname = make_valid_identifier (vname); // check again (in case vname was null, empty, or some such thing): ident_valid = octave::valid_identifier (vname); } H5Gget_objinfo (group_id, name, 1, &info); if (info.type == H5G_GROUP && ident_valid) { #if defined (HAVE_HDF5_18) subgroup_id = H5Gopen (group_id, name, octave_H5P_DEFAULT); #else subgroup_id = H5Gopen (group_id, name); #endif if (subgroup_id < 0) { retval = subgroup_id; goto done; } if (hdf5_check_attr (subgroup_id, "OCTAVE_NEW_FORMAT")) { #if defined (HAVE_HDF5_18) data_id = H5Dopen (subgroup_id, "type", octave_H5P_DEFAULT); #else data_id = H5Dopen (subgroup_id, "type"); #endif if (data_id < 0) { retval = data_id; goto done; } type_id = H5Dget_type (data_id); type_class_id = H5Tget_class (type_id); if (type_class_id != H5T_STRING) goto done; space_id = H5Dget_space (data_id); hsize_t rank = H5Sget_simple_extent_ndims (space_id); if (rank != 0) goto done; int slen = H5Tget_size (type_id); if (slen < 0) goto done; OCTAVE_LOCAL_BUFFER (char, typ, slen); // create datatype for (null-terminated) string to read into: hid_t st_id = H5Tcopy (H5T_C_S1); H5Tset_size (st_id, slen); if (H5Dread (data_id, st_id, octave_H5S_ALL, octave_H5S_ALL, octave_H5P_DEFAULT, typ) < 0) goto done; H5Tclose (st_id); H5Dclose (data_id); if (std::string (typ, slen-1) == "inline function") { retval = load_inline_fcn (subgroup_id, name, d->tc); } else { d->tc = type_info.lookup_type (std::string (typ, slen-1)); try { retval = (d->tc.load_hdf5 (subgroup_id, "value") ? 1 : -1); } catch (const octave::execution_exception& ee) { retval = -1; } } // check for OCTAVE_GLOBAL attribute: d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL"); H5Gclose (subgroup_id); } else { // It seems that this block only applies to an old list type // and that we shouldn't need to handle the old inline // function type here. // an HDF5 group is treated as an octave structure by // default (since that preserves name information), and an // octave list otherwise. if (hdf5_check_attr (subgroup_id, "OCTAVE_LIST")) d->tc = type_info.lookup_type ("list"); else d->tc = type_info.lookup_type ("struct"); // check for OCTAVE_GLOBAL attribute: d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL"); H5Gclose (subgroup_id); try { retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1); } catch (const octave::execution_exception& ee) { retval = -1; } } } else if (info.type == H5G_DATASET && ident_valid) { // It seems that this block only applies to an old version of // Octave HDF5 files and that it is probably not important to // handle the old inline function type here. // For backwards compatibility. #if defined (HAVE_HDF5_18) data_id = H5Dopen (group_id, name, octave_H5P_DEFAULT); #else data_id = H5Dopen (group_id, name); #endif if (data_id < 0) { retval = data_id; goto done; } type_id = H5Dget_type (data_id); type_class_id = H5Tget_class (type_id); if (type_class_id == H5T_FLOAT) { space_id = H5Dget_space (data_id); hsize_t rank = H5Sget_simple_extent_ndims (space_id); if (rank == 0) d->tc = type_info.lookup_type ("scalar"); else d->tc = type_info.lookup_type ("matrix"); H5Sclose (space_id); } else if (type_class_id == H5T_INTEGER) { // What integer type do we really have.. std::string int_typ; #if defined (HAVE_H5T_GET_NATIVE_TYPE) // FIXME: test this code and activated with an autoconf // test!! It is also incorrect for 64-bit indexing!! switch (H5Tget_native_type (type_id, H5T_DIR_ASCEND)) { case H5T_NATIVE_CHAR: int_typ = "int8 "; break; case H5T_NATIVE_SHORT: int_typ = "int16 "; break; case H5T_NATIVE_INT: case H5T_NATIVE_LONG: int_typ = "int32 "; break; case H5T_NATIVE_LLONG: int_typ = "int64 "; break; case H5T_NATIVE_UCHAR: int_typ = "uint8 "; break; case H5T_NATIVE_USHORT: int_typ = "uint16 "; break; case H5T_NATIVE_UINT: case H5T_NATIVE_ULONG: int_typ = "uint32 "; break; case H5T_NATIVE_ULLONG: int_typ = "uint64 "; break; } #else hid_t int_sign = H5Tget_sign (type_id); if (int_sign == H5T_SGN_ERROR) warning ("load: can't read '%s' (unknown datatype)", name); else { if (int_sign == H5T_SGN_NONE) int_typ.push_back ('u'); int_typ.append ("int"); int slen = H5Tget_size (type_id); if (slen < 0) warning ("load: can't read '%s' (unknown datatype)", name); else { switch (slen) { case 1: int_typ.append ("8 "); break; case 2: int_typ.append ("16 "); break; case 4: int_typ.append ("32 "); break; case 8: int_typ.append ("64 "); break; default: warning ("load: can't read '%s' (unknown datatype)", name); int_typ = ""; break; } } } #endif if (int_typ == "") warning ("load: can't read '%s' (unknown datatype)", name); else { // Matrix or scalar? space_id = H5Dget_space (data_id); hsize_t rank = H5Sget_simple_extent_ndims (space_id); if (rank == 0) int_typ.append ("scalar"); else int_typ.append ("matrix"); d->tc = type_info.lookup_type (int_typ); H5Sclose (space_id); } } else if (type_class_id == H5T_STRING) d->tc = type_info.lookup_type ("string"); else if (type_class_id == H5T_COMPOUND) { hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE); hid_t range_type = hdf5_make_range_type (H5T_NATIVE_DOUBLE); if (hdf5_types_compatible (type_id, complex_type)) { // read complex matrix or scalar variable space_id = H5Dget_space (data_id); hsize_t rank = H5Sget_simple_extent_ndims (space_id); if (rank == 0) d->tc = type_info.lookup_type ("complex scalar"); else d->tc = type_info.lookup_type ("complex matrix"); H5Sclose (space_id); } else if (hdf5_types_compatible (type_id, range_type)) { // If it's not a complex, check if it's a range d->tc = octave_value_typeinfo::lookup_type ("range"); } else // Otherwise, just ignore it with a warning. { warning ("load: can't read '%s' (unknown datatype)", name); retval = 0; // unknown datatype; skip return retval; } H5Tclose (range_type); H5Tclose (complex_type); } else { warning ("load: can't read '%s' (unknown datatype)", name); retval = 0; // unknown datatype; skip return retval; } // check for OCTAVE_GLOBAL attribute: d->global = hdf5_check_attr (data_id, "OCTAVE_GLOBAL"); try { retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1); } catch (const octave::execution_exception& ee) { retval = -1; } H5Tclose (type_id); H5Dclose (data_id); } if (! ident_valid) { // should we attempt to handle invalid identifiers by converting // bad characters to '_', say? warning ("load: skipping invalid identifier '%s' in hdf5 file", name); } done: if (retval < 0) { // Must be warning. A call to error aborts and leaves H5Giterate in // a mangled state that causes segfault on exit (bug #56149). warning ("load: error while reading hdf5 item '%s'", name); } if (retval > 0) { // get documentation string, if any: int comment_length = H5Gget_comment (group_id, name, 0, nullptr); if (comment_length > 1) { OCTAVE_LOCAL_BUFFER (char, tdoc, comment_length); H5Gget_comment (group_id, name, comment_length, tdoc); d->doc = tdoc; } else if (vname != name) { // the name was changed; store the original name // as the documentation string: d->doc = name; } // copy name (actually, vname): d->name = vname; } return retval; } #endif octave_hdf5_err hdf5_read_next_data (octave_hdf5_id group_id, const char *name, void *dv) { #if defined (HAVE_HDF5) hid_t new_id = check_hdf5_id_value (group_id, "hdf5_read_next_data"); return hdf5_read_next_data_internal (new_id, name, dv); #else err_disabled_feature ("hdf5_read_next_data", "HDF5"); #endif } octave_hdf5_err hdf5_h5g_iterate (octave_hdf5_id loc_id, const char *name, int *idx, void *operator_data) { #if defined (HAVE_HDF5) hid_t new_id = check_hdf5_id_value (loc_id, "hdf5_h5g_iterate"); return H5Giterate (new_id, name, idx, hdf5_read_next_data_internal, operator_data); #else err_disabled_feature ("hdf5_h5g_iterate", "HDF5"); #endif } // Read the next Octave variable from the stream IS, which must really be an // hdf5_ifstream. Return the variable value in tc, its docstring in doc, and // whether it is global in global. The return value is the name of the // variable, or NULL if none were found or there was an error. std::string read_hdf5_data (std::istream& is, const std::string& /* filename */, bool& global, octave_value& tc, std::string& doc, const string_vector& argv, int argv_idx, int argc) { #if defined (HAVE_HDF5) octave::check_hdf5_types (); std::string retval; doc.clear (); hdf5_ifstream& hs = dynamic_cast<hdf5_ifstream&> (is); hdf5_callback_data d; herr_t H5Giterate_retval = -1; hsize_t num_obj = 0; #if defined (HAVE_HDF5_18) hid_t group_id = H5Gopen (hs.file_id, "/", octave_H5P_DEFAULT); #else hid_t group_id = H5Gopen (hs.file_id, "/"); #endif H5Gget_num_objs (group_id, &num_obj); H5Gclose (group_id); // For large datasets and out-of-core functionality, // check if only parts of the data is requested bool load_named_vars = argv_idx < argc; while (load_named_vars && hs.current_item < static_cast<int> (num_obj)) { std::vector<char> var_name; bool found = false; std::size_t len = 0; len = H5Gget_objname_by_idx (hs.file_id, hs.current_item, nullptr, 0); var_name.resize (len+1); H5Gget_objname_by_idx (hs.file_id, hs.current_item, &var_name[0], len+1); for (int i = argv_idx; i < argc; i++) { glob_match pattern (argv[i]); if (pattern.match (std::string (&var_name[0]))) { found = true; break; } } if (found) break; hs.current_item++; } if (hs.current_item < static_cast<int> (num_obj)) H5Giterate_retval = H5Giterate (hs.file_id, "/", &hs.current_item, hdf5_read_next_data_internal, &d); if (H5Giterate_retval > 0) { global = d.global; tc = d.tc; doc = d.doc; } else { // An error occurred (H5Giterate_retval < 0), // or there are no more datasets (H5Giterate_retval == 0). // hdf5_read_next_data_internal has already printed a warning msg. } if (! d.name.empty ()) retval = d.name; return retval; #else err_disabled_feature ("read_hdf5_data", "HDF5"); #endif } // Add an attribute named attr_name to loc_id (a simple scalar // attribute with value 1). Return value is >= 0 on success. octave_hdf5_err hdf5_add_attr (octave_hdf5_id loc_id, const char *attr_name) { #if defined (HAVE_HDF5) herr_t retval = 0; hid_t as_id = H5Screate (H5S_SCALAR); if (as_id >= 0) { #if defined (HAVE_HDF5_18) hid_t a_id = H5Acreate (loc_id, attr_name, H5T_NATIVE_UCHAR, as_id, octave_H5P_DEFAULT, octave_H5P_DEFAULT); #else hid_t a_id = H5Acreate (loc_id, attr_name, H5T_NATIVE_UCHAR, as_id, octave_H5P_DEFAULT); #endif if (a_id >= 0) { unsigned char attr_val = 1; retval = H5Awrite (a_id, H5T_NATIVE_UCHAR, &attr_val); H5Aclose (a_id); } else retval = a_id; H5Sclose (as_id); } else retval = as_id; return retval; #else err_disabled_feature ("hdf5_add_attr", "HDF5"); #endif } octave_hdf5_err hdf5_add_scalar_attr (octave_hdf5_id loc_id, octave_hdf5_id type_id, const char *attr_name, void *buf) { #if defined (HAVE_HDF5) herr_t retval = 0; hid_t as_id = H5Screate (H5S_SCALAR); if (as_id >= 0) { #if defined (HAVE_HDF5_18) hid_t a_id = H5Acreate (loc_id, attr_name, type_id, as_id, octave_H5P_DEFAULT, octave_H5P_DEFAULT); #else hid_t a_id = H5Acreate (loc_id, attr_name, type_id, as_id, octave_H5P_DEFAULT); #endif if (a_id >= 0) { retval = H5Awrite (a_id, type_id, buf); H5Aclose (a_id); } else retval = a_id; H5Sclose (as_id); } else retval = as_id; return retval; #else err_disabled_feature ("hdf5_add_scalar_attr", "HDF5"); #endif } // Save an empty matrix, if needed. Returns // > 0 Saved empty matrix // = 0 Not an empty matrix; did nothing // < 0 Error condition int save_hdf5_empty (octave_hdf5_id loc_id, const char *name, const dim_vector& d) { #if defined (HAVE_HDF5) hsize_t sz = d.length (); OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, sz); bool empty = false; hid_t space_hid = -1; hid_t data_hid = -1; int retval; for (hsize_t i = 0; i < sz; i++) { dims[i] = d(i); if (dims[i] < 1) empty = true; } if (! empty) return 0; space_hid = H5Screate_simple (1, &sz, nullptr); if (space_hid < 0) return space_hid; #if defined (HAVE_HDF5_18) data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid, octave_H5P_DEFAULT, octave_H5P_DEFAULT, octave_H5P_DEFAULT); #else data_hid = H5Dcreate (loc_id, name, H5T_NATIVE_IDX, space_hid, octave_H5P_DEFAULT); #endif if (data_hid < 0) { H5Sclose (space_hid); return data_hid; } retval = H5Dwrite (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL, octave_H5P_DEFAULT, dims) >= 0; H5Dclose (data_hid); H5Sclose (space_hid); if (retval) retval = hdf5_add_attr (loc_id, "OCTAVE_EMPTY_MATRIX"); return (retval == 0 ? 1 : retval); #else err_disabled_feature ("save_hdf5_empty", "HDF5"); #endif } // Load an empty matrix, if needed. Returns // > 0 loaded empty matrix, dimensions returned // = 0 Not an empty matrix; did nothing // < 0 Error condition int load_hdf5_empty (octave_hdf5_id loc_id, const char *name, dim_vector& d) { #if defined (HAVE_HDF5) if (! hdf5_check_attr (loc_id, "OCTAVE_EMPTY_MATRIX")) return 0; hsize_t hdims, maxdims; #if defined (HAVE_HDF5_18) hid_t data_hid = H5Dopen (loc_id, name, octave_H5P_DEFAULT); #else hid_t data_hid = H5Dopen (loc_id, name); #endif hid_t space_id = H5Dget_space (data_hid); H5Sget_simple_extent_dims (space_id, &hdims, &maxdims); int retval; OCTAVE_LOCAL_BUFFER (octave_idx_type, dims, hdims); retval = H5Dread (data_hid, H5T_NATIVE_IDX, octave_H5S_ALL, octave_H5S_ALL, octave_H5P_DEFAULT, dims); if (retval >= 0) { d.resize (hdims); for (hsize_t i = 0; i < hdims; i++) d(i) = dims[i]; } H5Sclose (space_id); H5Dclose (data_hid); return (retval == 0 ? hdims : retval); #else err_disabled_feature ("load_hdf5_empty", "HDF5"); #endif } // save_type_to_hdf5 is not currently used, since hdf5 doesn't yet support // automatic float<->integer conversions: // return the HDF5 type id corresponding to the Octave save_type octave_hdf5_id save_type_to_hdf5 (save_type st) { #if defined (HAVE_HDF5) # if defined (HAVE_HDF5_INT2FLOAT_CONVERSIONS) switch (st) { case LS_U_CHAR: return H5T_NATIVE_UCHAR; case LS_U_SHORT: return H5T_NATIVE_USHORT; case LS_U_INT: return H5T_NATIVE_UINT; case LS_CHAR: return H5T_NATIVE_CHAR; case LS_SHORT: return H5T_NATIVE_SHORT; case LS_INT: return H5T_NATIVE_INT; case LS_FLOAT: return H5T_NATIVE_FLOAT; case LS_DOUBLE: default: return H5T_NATIVE_DOUBLE; } # else octave_unused_parameter (st); return -1; # endif #else octave_unused_parameter (st); err_disabled_feature ("save_type_to_hdf5", "HDF5"); #endif } // Add the data from TC to the HDF5 location loc_id, which could // be either a file or a group within a file. Return true if // successful. This function calls itself recursively for lists // (stored as HDF5 groups). 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) { #if defined (HAVE_HDF5) hsize_t dims[3]; hid_t type_id, space_id, data_id, data_type_id; type_id = space_id = data_id = data_type_id = -1; bool retval = false; octave_value val = tc; // FIXME: diagonal & permutation matrices currently don't know how to save // themselves, so we convert them first to normal matrices using A = A(:,:). // This is a temporary hack. if (val.is_diag_matrix () || val.is_perm_matrix () || val.type_id () == octave_lazy_index::static_type_id ()) val = val.full_value (); std::string t = val.type_name (); #if defined (HAVE_HDF5_18) data_id = H5Gcreate (loc_id, name.c_str (), octave_H5P_DEFAULT, octave_H5P_DEFAULT, octave_H5P_DEFAULT); #else data_id = H5Gcreate (loc_id, name.c_str (), 0); #endif if (data_id < 0) goto error_cleanup; // attach the type of the variable type_id = H5Tcopy (H5T_C_S1); H5Tset_size (type_id, t.length () + 1); if (type_id < 0) goto error_cleanup; dims[0] = 0; space_id = H5Screate_simple (0, dims, nullptr); if (space_id < 0) goto error_cleanup; #if defined (HAVE_HDF5_18) data_type_id = H5Dcreate (data_id, "type", type_id, space_id, octave_H5P_DEFAULT, octave_H5P_DEFAULT, octave_H5P_DEFAULT); #else data_type_id = H5Dcreate (data_id, "type", type_id, space_id, octave_H5P_DEFAULT); #endif if (data_type_id < 0 || H5Dwrite (data_type_id, type_id, octave_H5S_ALL, octave_H5S_ALL, octave_H5P_DEFAULT, t.c_str ()) < 0) goto error_cleanup; // Now call the real function to save the variable retval = val.save_hdf5 (data_id, "value", save_as_floats); // attach doc string as comment: if (retval && doc.length () > 0 && H5Gset_comment (loc_id, name.c_str (), doc.c_str ()) < 0) retval = false; // if it's global, add an attribute "OCTAVE_GLOBAL" with value 1 if (retval && mark_global) retval = hdf5_add_attr (data_id, "OCTAVE_GLOBAL") >= 0; // We are saving in the new variable format, so mark it if (retval) retval = hdf5_add_attr (data_id, "OCTAVE_NEW_FORMAT") >= 0; error_cleanup: if (data_type_id >= 0) H5Dclose (data_type_id); if (type_id >= 0) H5Tclose (type_id); if (space_id >= 0) H5Sclose (space_id); if (data_id >= 0) H5Gclose (data_id); if (! retval) error ("save: error while writing '%s' to hdf5 file", name.c_str ()); return retval; #else err_disabled_feature ("add_hdf5_data", "HDF5"); #endif } // Write data from TC in HDF5 (binary) format to the stream OS, // which must be an hdf5_ofstream, returning true on success. 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) { #if defined (HAVE_HDF5) octave::check_hdf5_types (); hdf5_ofstream& hs = dynamic_cast<hdf5_ofstream&> (os); return add_hdf5_data (hs.file_id, tc, name, doc, mark_global, save_as_floats); #else err_disabled_feature ("save_hdf5_data", "HDF5"); #endif } #endif