# HG changeset patch # User Lachlan Andrew # Date 1456469608 -39600 # Node ID ac59b72712fd9af86afb947be735c2b06b14eb38 # Parent 4bf980861fd621e6ea7e8457923953fb8892ab83 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. diff -r 4bf980861fd6 -r ac59b72712fd liboctave/array/Sparse.cc --- 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 +std::istream& +read_sparse_matrix (std::istream& is, Sparse& 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; - + template class API Sparse; \ + template std::istream& read_sparse_matrix \ + (std::istream& is, Sparse& a, T (*read_fcn) (std::istream&)); diff -r 4bf980861fd6 -r ac59b72712fd liboctave/array/Sparse.h --- 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 std::istream& read_sparse_matrix (std::istream& is, Sparse& 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