changeset 2511:9b0dd36714eb

[project @ 1996-11-14 02:57:33 by jwe]
author jwe
date Thu, 14 Nov 1996 03:00:12 +0000
parents 0be4639a6c13
children fda09c1e787e
files NEWS PROJECTS src/ChangeLog src/load-save.cc
diffstat 4 files changed, 186 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS
+++ b/NEWS
@@ -24,6 +24,11 @@
     available to make them behave in a way that is compatible with
     previous versions of Octave.
 
+  * Octave can now read files that contain columns of numbers only,
+    with no header information.  The name of the loaded variable is
+    constructed from the file name.  Each line in the file must have
+    the same number of elements.
+
   * The interface to the pager has changed.  The new built-in variable
     `page_output_immediately' controls when Octave sends output to the
     pager.  If it is nonzero, Octave sends output to the pager as soon
--- a/PROJECTS
+++ b/PROJECTS
@@ -164,9 +164,6 @@
     working on them, it would be good to support other size
     specifications (integer*2, etc.).
 
-  * Make load work to read files that contain numbers only, and put
-    the values in a matrix named after the file.
-
   * Make load and save work for structures.
 
   * Make load and save look for <file>.mat if only given <file>.
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,12 @@
 Wed Nov 13 11:13:22 1996  John W. Eaton  <jwe@bevo.che.wisc.edu>
 
+	* load-save.cc (read_mat_ascii_matrix, get_lines_and_columns,
+	get_complete_line): New functions, for reading headless text files.
+	(load_save_format): Add LS_MAT_ASCII, for headless text files.
+	(do_load): Handle LS_MAT_ASCII files.
+	Thanks to Mel Melchner <mjm@research.att.com> for initial version
+	of this code.
+
 	* sysdep.cc: Conditionally include ieeefp.h.
 	(BSD_init, SCO_init): New functions.
 	(sysdep_init): Conditionally call them here.
--- a/src/load-save.cc
+++ b/src/load-save.cc
@@ -73,6 +73,7 @@
   {
     LS_ASCII,
     LS_BINARY,
+    LS_MAT_ASCII,
     LS_MAT_BINARY,
     LS_UNKNOWN,
   };
@@ -909,6 +910,152 @@
   return name;
 }
 
+// Get a complete line of input.
+
+static string
+get_complete_line (istream& is)
+{
+  string retval;
+
+  ostrstream buf;
+
+  char c;
+
+  while (is.get (c))
+    {
+      if (c == '\n')
+	break;
+
+      buf << c;
+    }
+
+  buf << ends;
+
+  char *tmp = buf.str ();
+
+  retval = tmp;
+
+  delete [] tmp;
+
+  return retval;
+}
+
+static void
+get_lines_and_columns (istream& is, const string& filename, int& nr, int& nc)
+{
+  streampos pos = is.tellg ();
+
+  int file_line_number = 0;
+
+  nr = 0;
+  nc = 0;
+
+  while (! (is.eof () || error_state))
+    {
+      string line = get_complete_line (is);
+
+      file_line_number++;
+
+      size_t beg = line.find_first_not_of (" \t");
+
+      if (beg != NPOS)
+	{
+	  int tmp_nc = 0;
+
+	  while (beg != NPOS)
+	    {
+	      tmp_nc++;
+
+	      size_t end = line.find_first_of (" \t", beg);
+
+	      if (end != NPOS)
+		beg = line.find_first_not_of (" \t", end);
+	      else
+		break;
+	    }
+
+	  if (nc == 0)
+	    {
+	      nc = tmp_nc;
+	      nr++;
+	    }
+	  else if (nc == tmp_nc)
+	    nr++;
+	  else
+	    error ("load: %s: inconsistent number of columns near line %d",
+		   filename.c_str (), file_line_number);
+	}
+    }
+
+  if (nr == 0 || nc == 0)
+    error ("load: file `%s' seems to be empty!", filename.c_str ());
+
+  is.clear ();
+  is.seekg (pos, ios::beg);
+}
+
+// Extract a matrix from a file of numbers only.
+//
+// Comments are not allowed.  The file should only have numeric values.
+//
+// Reads the file twice.  Once to find the number of rows and columns,
+// and once to extract the matrix.
+//
+// FILENAME is used for error messages.
+//
+// This format provides no way to tag the data as global.
+
+static char *
+read_mat_ascii_data (istream& is, const string& filename,
+		     octave_value& tc)
+{
+  char *name = 0;
+
+  string varname;
+
+  size_t pos = filename.find ('.');
+
+  if (pos != NPOS)
+    varname = filename.substr (0, pos);
+  else
+    varname = filename;
+
+  if (valid_identifier (varname.c_str ()))
+    {
+      int nr = 0;
+      int nc = 0;
+
+      get_lines_and_columns (is, filename, nr, nc);
+
+      if (! error_state)
+	{
+	  // NR and NC must be greater than zero if we end up here.
+
+	  Matrix tmp (nr, nc);
+
+	  is >> tmp;
+
+	  if (is)
+	    {
+	      tc = tmp;
+
+	      name = strsave (varname.c_str ());
+	    }
+	  else
+	    error ("load: failed to read matrix from file `%s'",
+		   filename.c_str ());
+	}
+      else
+	error ("load: unable to extract matrix size from file `%s'",
+	       filename.c_str ());
+    }
+  else
+    error ("load: unable to convert filename `%s' to valid identifier",
+	   filename.c_str ());
+
+  return name;
+}
+
 // Read LEN elements of data from IS in the format specified by
 // PRECISION, placing the result in DATA.  If SWAP is nonzero, swap
 // the bytes of each element before copying to DATA.  FLT_FMT
@@ -1287,6 +1434,7 @@
 	retval = LS_MAT_BINARY;
       else
 	{
+	  file.clear ();
 	  file.seekg (0, ios::beg);
 
 	  char *tmp = extract_keyword (file, "name");
@@ -1294,8 +1442,20 @@
 	  if (tmp)
 	    {
 	      retval = LS_ASCII;
+
 	      delete [] tmp;
 	    }
+	  else
+	    {
+	      // Try reading the file as numbers only, determining the
+	      // number of rows and columns from the data.  We don't
+	      // even bother to check to see if the first item in the
+	      // file is a number, so that get_complete_line() can
+	      // skip any comments that might appear at the top of the
+	      // file.
+
+	      retval = LS_MAT_ASCII;
+	    }
 	}
     }
 
@@ -1337,6 +1497,10 @@
 				   global, tc, doc);
 	  break;
 
+	case LS_MAT_ASCII:
+	  name = read_mat_ascii_data (stream, orig_fname, tc);
+	  break;
+
 	case LS_MAT_BINARY:
 	  name = read_mat_binary_data (stream, orig_fname, tc);
 	  break;
@@ -1350,6 +1514,7 @@
 	{
 	  delete [] name;
 	  delete [] doc;
+
 	  break;
 	}
       else if (! error_state && name)
@@ -1382,6 +1547,14 @@
 		      install_loaded_variable (force, name, tc, global, doc);
 		    }
 		}
+
+	      delete [] name;
+	      delete [] doc;
+
+	      // Only attempt to read one item from a headless text file.
+
+	      if (format == LS_MAT_ASCII)
+		break;
 	    }
 	  else
 	    error ("load: unable to load variable `%s'", name);
@@ -1394,11 +1567,9 @@
 
 	  delete [] name;
 	  delete [] doc;
+
 	  break;
 	}
-
-      delete [] name;
-      delete [] doc;
     }
 
   if (list_only && count)