changeset 21704:ac59b72712fd

Clearer error messages when loading buggy sparse matrix files (bug #38414) * Sparse.h (load_sparse_matrix): Move to Sparse.cc * Sparse.cc (load_sparse_matrix): Print element number in all errors. If reading fails, print the offending field.
author Lachlan Andrew <lachlanbis@gmail.com>
date Fri, 26 Feb 2016 17:53:28 +1100
parents 4bf980861fd6
children 764e586dca4b
files liboctave/array/Sparse.cc liboctave/array/Sparse.h
diffstat 2 files changed, 108 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/array/Sparse.cc	Sat May 14 10:17:11 2016 +1000
+++ b/liboctave/array/Sparse.cc	Fri Feb 26 17:53:28 2016 +1100
@@ -2681,6 +2681,110 @@
   return retval;
 }
 
+template <typename T>
+std::istream&
+read_sparse_matrix (std::istream& is, Sparse<T>& a,
+                    T (*read_fcn) (std::istream&))
+{
+  octave_idx_type nr = a.rows ();
+  octave_idx_type nc = a.cols ();
+  octave_idx_type nz = a.nzmax ();
+
+  if (nr > 0 && nc > 0)
+    {
+      octave_idx_type itmp;
+      octave_idx_type jtmp;
+      octave_idx_type iold = 0;
+      octave_idx_type jold = 0;
+      octave_idx_type ii = 0;
+      T tmp;
+
+      a.cidx (0) = 0;
+      for (octave_idx_type i = 0; i < nz; i++)
+        {
+          itmp = 0; jtmp = 0;
+          is >> itmp;
+          itmp--;
+
+          is >> jtmp;
+          jtmp--;
+
+          if (is.fail ())
+            {
+              is.clear();
+              std::string err_field;
+              is >> err_field;
+              (*current_liboctave_error_handler)
+                ("invalid sparse matrix: element %d: "
+                 "Symbols '%s' is not an integer format",
+                 i+1, err_field.c_str ());
+            }
+
+          if (itmp < 0 || itmp >= nr)
+            {
+              is.setstate (std::ios::failbit);
+
+              (*current_liboctave_error_handler)
+                ("invalid sparse matrix: element %d: "
+                 "row index = %d out of range",
+                 i+1, itmp + 1);
+            }
+
+          if (jtmp < 0 || jtmp >= nc)
+            {
+              is.setstate (std::ios::failbit);
+
+              (*current_liboctave_error_handler)
+                ("invalid sparse matrix: element %d: "
+                 "column index = %d out of range",
+                 i+1, jtmp + 1);
+            }
+
+          if (jtmp < jold)
+            {
+              is.setstate (std::ios::failbit);
+
+              (*current_liboctave_error_handler)
+                ("invalid sparse matrix: element %d:"
+                 "column indices must appear in ascending order (%d < %d)",
+                 i+1, jtmp, jold);
+            }
+          else if (jtmp > jold)
+            {
+              for (octave_idx_type j = jold; j < jtmp; j++)
+                a.cidx (j+1) = ii;
+            }
+          else if (itmp < iold)
+            {
+              is.setstate (std::ios::failbit);
+
+              (*current_liboctave_error_handler)
+                ("invalid sparse matrix: element %d: "
+                 "row indices must appear in ascending order in each column "
+                 "(%d < %d)",
+                 i+1, iold, itmp);
+            }
+
+          iold = itmp;
+          jold = jtmp;
+
+          tmp = read_fcn (is);
+
+          if (! is)
+            return is;  // Problem, return is in error state
+
+          a.data (ii) = tmp;
+          a.ridx (ii++) = itmp;
+        }
+
+      for (octave_idx_type j = jold; j < nc; j++)
+        a.cidx (j+1) = ii;
+    }
+
+  return is;
+}
+
+
 /*
  * Tests
  *
@@ -2898,5 +3002,6 @@
 }
 
 #define INSTANTIATE_SPARSE(T, API) \
-  template class API Sparse<T>;
-
+  template class API Sparse<T>; \
+  template std::istream& read_sparse_matrix<T> \
+    (std::istream& is, Sparse<T>& a, T (*read_fcn) (std::istream&));
--- a/liboctave/array/Sparse.h	Sat May 14 10:17:11 2016 +1000
+++ b/liboctave/array/Sparse.h	Fri Feb 26 17:53:28 2016 +1100
@@ -697,88 +697,6 @@
 template <typename T>
 std::istream&
 read_sparse_matrix (std::istream& is, Sparse<T>& a,
-                    T (*read_fcn) (std::istream&))
-{
-  octave_idx_type nr = a.rows ();
-  octave_idx_type nc = a.cols ();
-  octave_idx_type nz = a.nzmax ();
-
-  if (nr > 0 && nc > 0)
-    {
-      octave_idx_type itmp;
-      octave_idx_type jtmp;
-      octave_idx_type iold = 0;
-      octave_idx_type jold = 0;
-      octave_idx_type ii = 0;
-      T tmp;
-
-      a.cidx (0) = 0;
-      for (octave_idx_type i = 0; i < nz; i++)
-        {
-          itmp = 0; jtmp = 0;
-          is >> itmp;
-          itmp--;
-
-          is >> jtmp;
-          jtmp--;
-
-          if (itmp < 0 || itmp >= nr)
-            {
-              is.setstate (std::ios::failbit);
-
-              (*current_liboctave_error_handler)
-                ("invalid sparse matrix: row index = %d out of range",
-                 itmp + 1);
-            }
-
-          if (jtmp < 0 || jtmp >= nc)
-            {
-              is.setstate (std::ios::failbit);
-
-              (*current_liboctave_error_handler)
-                ("invalid sparse matrix: column index = %d out of range",
-                 jtmp + 1);
-            }
-
-          if (jtmp < jold)
-            {
-              is.setstate (std::ios::failbit);
-
-              (*current_liboctave_error_handler)
-                ("invalid sparse matrix: "
-                 "column indices must appear in ascending order");
-            }
-          else if (jtmp > jold)
-            {
-              for (octave_idx_type j = jold; j < jtmp; j++)
-                a.cidx (j+1) = ii;
-            }
-          else if (itmp < iold)
-            {
-              is.setstate (std::ios::failbit);
-
-              (*current_liboctave_error_handler)
-                ("invalid sparse matrix: "
-                 "row indices must appear in ascending order in each column");
-            }
-
-          iold = itmp;
-          jold = jtmp;
-
-          tmp = read_fcn (is);
-
-          if (! is)
-            return is;  // Problem, return is in error state
-
-          a.data (ii) = tmp;
-          a.ridx (ii++) = itmp;
-        }
-
-      for (octave_idx_type j = jold; j < nc; j++)
-        a.cidx (j+1) = ii;
-    }
-
-  return is;
-}
+                    T (*read_fcn) (std::istream&));
 
 #endif