changeset 27142:9e5c1d343a2c

Skip HDF5 elements which are unrecognized, but continue reading file (bug #32756). * ls-hdf5.cc (hdf5_make_range_type): New function. * ls-hdf5.cc (hdf5_read_next_data_internal): create a new range_type variable with hdf5_make_range_type(). When decoding element type, check whether element is a range with df5_types_compatible and range_type variable. If decode fails, issue a warning and continue.
author Daniel Davis <ddesics@gmail.com>
date Mon, 03 Jun 2019 19:03:15 -0700
parents 30f53f7a7293
children 1bad33112465
files libinterp/corefcn/ls-hdf5.cc
diffstat 1 files changed, 32 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/ls-hdf5.cc	Mon Jun 03 09:04:41 2019 -0700
+++ b/libinterp/corefcn/ls-hdf5.cc	Mon Jun 03 19:03:15 2019 -0700
@@ -414,6 +414,24 @@
 
 #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;
+}
+
 // 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
@@ -686,6 +704,7 @@
       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))
             {
@@ -700,17 +719,25 @@
 
               H5Sclose (space_id);
             }
-          else
-            // Assume that if its not complex its a range.
-            // If its not, it'll be rejected later in the range code.
-            d->tc = type_info.lookup_type ("range");
+          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
+          retval = 0;  // unknown datatype; skip
           return retval;
         }