diff src/ls-oct-ascii.cc @ 4687:e95c86d48732

[project @ 2004-01-06 21:53:34 by jwe]
author jwe
date Tue, 06 Jan 2004 21:53:34 +0000
parents 79fe96966ca0
children 14dc2267c343
line wrap: on
line diff
--- a/src/ls-oct-ascii.cc	Tue Jan 06 19:31:57 2004 +0000
+++ b/src/ls-oct-ascii.cc	Tue Jan 06 21:53:34 2004 +0000
@@ -26,7 +26,6 @@
 #include <config.h>
 #endif
 
-#include <cfloat>
 #include <cstring>
 #include <cctype>
 
@@ -71,27 +70,8 @@
 // The number of decimal digits to use when writing ascii data.
 static int Vsave_precision;
 
-#define CELL_ELT_TAG "<cell-element>"
-
-// Used when converting Inf to something that gnuplot can read.
-
-#ifndef OCT_RBV
-#define OCT_RBV DBL_MAX / 100.0
-#endif
-
 // Functions for reading ascii data.
 
-static void
-ascii_save_type (std::ostream& os, const char *type, bool mark_as_global)
-{
-  if (mark_as_global)
-    os << "# type: global ";
-  else
-    os << "# type: ";
-
-  os << type << "\n";
-}
-
 static Matrix
 strip_infnan (const Matrix& m)
 {
@@ -123,69 +103,6 @@
   return retval;
 }
 
-static ComplexMatrix
-strip_infnan (const ComplexMatrix& m)
-{
-  int nr = m.rows ();
-  int nc = m.columns ();
-
-  ComplexMatrix retval (nr, nc);
-
-  int k = 0;
-  for (int i = 0; i < nr; i++)
-    {
-      for (int j = 0; j < nc; j++)
-	{
-	  Complex c = m (i, j);
-	  if (xisnan (c))
-	    goto next_row;
-	  else
-	    {
-	      double re = real (c);
-	      double im = imag (c);
-
-	      re = xisinf (re) ? (re > 0 ? OCT_RBV : -OCT_RBV) : re;
-	      im = xisinf (im) ? (im > 0 ? OCT_RBV : -OCT_RBV) : im;
-
-	      retval (k, j) = Complex (re, im);
-	    }
-	}
-      k++;
-
-    next_row:
-      continue;
-    }
-
-  if (k > 0)
-    retval.resize (k, nc);
-
-  return retval;
-}
-
-// Skip white space and comments on stream IS.
-
-static void
-skip_comments (std::istream& is)
-{
-  char c = '\0';
-  while (is.get (c))
-    {
-      if (c == ' ' || c == '\t' || c == '\n')
-	; // Skip whitespace on way to beginning of next line.
-      else
-	break;
-    }
-
-  for (;;)
-    {
-      if (is && (c == '%' || c == '#'))
-	while (is.get (c) && c != '\n')
-	  ; // Skip to beginning of next line, ignoring everything.
-      else
-	break;
-    }
-}
-
 // Extract a KEYWORD and its value from stream IS, returning the
 // associated value in a new string.
 //
@@ -194,7 +111,7 @@
 //  [%#][ \t]*keyword[ \t]*:[ \t]*string-value[ \t]*\n
 
 std::string
-extract_keyword (std::istream& is, const char *keyword)
+extract_keyword (std::istream& is, const char *keyword, const bool next_only)
 {
   std::string retval;
 
@@ -236,6 +153,8 @@
 	      OSSTREAM_FREEZE (value);
 	      break;
 	    }
+	  else if (next_only)
+	    break;
 	}
     }
 
@@ -267,8 +186,9 @@
 //
 //  [%#][ \t]*keyword[ \t]*int-value.*\n
 
-static bool
-extract_keyword (std::istream& is, const char *keyword, int& value)
+bool
+extract_keyword (std::istream& is, const char *keyword, int& value, 
+		 const bool next_only)
 {
   bool status = false;
   value = 0;
@@ -308,6 +228,8 @@
 		; // Skip to beginning of next line;
 	      break;
 	    }
+	  else if (next_only)
+	    break;
 	}
     }
   return status;
@@ -317,6 +239,9 @@
 // place it in TC, returning the name of the variable.  If the value
 // is tagged as global in the file, return TRUE in GLOBAL.
 //
+// Each type supplies its own function to load the data, and so this
+// function is extensible.
+//
 // FILENAME is used for error messages.
 //
 // The data is expected to be in the following format:
@@ -334,7 +259,7 @@
 // # type: <type>
 // # <info>
 //
-// Where:
+// Where, for the built in types are:
 //
 //  <name> : a valid identifier
 //
@@ -345,21 +270,25 @@
 //             | complex scalar
 //             | matrix
 //             | complex matrix
+//             | bool
+//             | bool matrix
 //             | string
 //             | range
-//             | string array
 //
 //  <info> : <matrix info>
 //         | <string info>
-//         | <string array info>
 //
 //  <matrix info> : # rows: <integer>
 //                : # columns: <integer>
 //
-//  <string info> : # length: <integer>
+//  <string info> : # elements: <integer>
+//                : # length: <integer> (once before each string)
 //
-//  <string array info> : # elements: <integer>
-//                      : # length: <integer> (once before each string)
+//  For backward compatibility the type "string array" is treated as a
+// "string" type. Also "string" can have a single element with no elements
+// line such that
+//
+//  <string info> : # length: <integer>
 //
 // Formatted ASCII data follows the header.
 //
@@ -375,7 +304,7 @@
 // Example:
 //
 //  # name: foo
-//  # type: string array
+//  # type: string
 //  # elements: 5
 //  # length: 4
 //  this
@@ -389,7 +318,8 @@
 //  array
 //
 // XXX FIXME XXX -- this format is fairly rigid, and doesn't allow for
-// arbitrary comments, etc.  Someone should fix that.
+// arbitrary comments.  Someone should fix that. It does allow arbitrary
+// types however.
 
 // Ugh.  The signature of the compare method is not standard in older
 // versions of the GNU libstdc++.  Do this instead:
@@ -442,196 +372,13 @@
       else
 	typ = tag;
 
-      if (SUBSTRING_COMPARE_EQ (typ, 0, 6, "scalar"))
-	{
-	  double tmp = octave_read_double (is);
-	  if (is)
-	    tc = tmp;
-	  else
-	    error ("load: failed to load scalar constant");
-	}
-      else if (SUBSTRING_COMPARE_EQ (typ, 0, 6, "matrix"))
-	{
-	  int nr = 0;
-	  int nc = 0;
-
-	  if (extract_keyword (is, "rows", nr) && nr >= 0
-	      && extract_keyword (is, "columns", nc) && nc >= 0)
-	    {
-	      if (nr > 0 && nc > 0)
-		{
-		  Matrix tmp (nr, nc);
-		  is >> tmp;
-		  if (is)
-		    tc = tmp;
-		  else
-		    error ("load: failed to load matrix constant");
-		}
-	      else if (nr == 0 || nc == 0)
-		tc = Matrix (nr, nc);
-	      else
-		panic_impossible ();
-	    }
-	  else
-	    error ("load: failed to extract number of rows and columns");
-	}
-      else if (SUBSTRING_COMPARE_EQ (typ, 0, 4, "cell"))
-	{
-	  int nr = 0;
-	  int nc = 0;
-
-	  if (extract_keyword (is, "rows",    nr) && nr >= 0
-	      && extract_keyword (is, "columns", nc) && nc >= 0)
-	    {
-	      if (nr > 0 && nc > 0)
-		{
-		  Cell tmp (nr, nc);
-
-		  for (int j = 0; j < nc; j++)
-		    {
-		      for (int i = 0; i < nr; i++)
-			{
-			  octave_value t2;
-
-			  // recurse to read cell elements
-			  std::string nm
-			    = read_ascii_data (is, filename, global, t2, count);
-
-			  if (nm == CELL_ELT_TAG)
-			    {
-			      if (is)
-				tmp.elem (i, j) = t2;
-			    }
-			  else
-			    {
-			      error ("load: cell array element had unexpected name");
-			      goto cell_read_error;
-			    }
-			}
-		    }
-
-		cell_read_error:
+      // Special case for backward compatiablity. A small bit of cruft
+      if (SUBSTRING_COMPARE_EQ (typ, 0, 12, "string array"))
+	tc = octave_value (charMatrix (), true);
+      else
+	tc = octave_value_typeinfo::lookup_type (typ);
 
-		  if (is)
-		    tc = tmp;
-		  else
-		    error ("load: failed to load cell element");
-		}
-	      else if (nr == 0 || nc == 0)
-		tc = Cell (nr, nc);
-	      else
-		panic_impossible ();
-	    }
-	  else
-	    error ("load: failed to extract number of rows and columns for cell array");
-	}
-      else if (SUBSTRING_COMPARE_EQ (typ, 0, 14, "complex scalar"))
-	{
-	  Complex tmp = octave_read_complex (is);
-	  if (is)
-	    tc = tmp;
-	  else
-	    error ("load: failed to load complex scalar constant");
-	}
-      else if (SUBSTRING_COMPARE_EQ (typ, 0, 14, "complex matrix"))
-	{
-	  int nr = 0;
-	  int nc = 0;
-
-	  if (extract_keyword (is, "rows", nr) && nr > 0
-	      && extract_keyword (is, "columns", nc) && nc > 0)
-	    {
-	      ComplexMatrix tmp (nr, nc);
-	      is >> tmp;
-	      if (is)
-		tc = tmp;
-	      else
-		error ("load: failed to load complex matrix constant");
-	    }
-	  else
-	    error ("load: failed to extract number of rows and columns");
-	}
-      else if (SUBSTRING_COMPARE_EQ (typ, 0, 12, "string array"))
-	{
-	  int elements;
-	  if (extract_keyword (is, "elements", elements) && elements >= 0)
-	    {
-	      // XXX FIXME XXX -- need to be able to get max length
-	      // before doing anything.
-
-	      charMatrix chm (elements, 0);
-	      int max_len = 0;
-	      for (int i = 0; i < elements; i++)
-		{
-		  int len;
-		  if (extract_keyword (is, "length", len) && len >= 0)
-		    {
-		      OCTAVE_LOCAL_BUFFER (char, tmp, len+1);
-
-		      if (len > 0 && ! is.read (X_CAST (char *, tmp), len))
-			{
-			  error ("load: failed to load string constant");
-			  break;
-			}
-		      else
-			{
-			  tmp [len] = '\0';
-			  if (len > max_len)
-			    {
-			      max_len = len;
-			      chm.resize (elements, max_len, 0);
-			    }
-			  chm.insert (tmp, i, 0);
-			}
-		    }
-		  else
-		    error ("load: failed to extract string length for element %d", i+1);
-		}
-
-	      if (! error_state)
-		tc = octave_value (chm, true);
-	    }
-	  else
-	    error ("load: failed to extract number of string elements");
-	}
-      else if (SUBSTRING_COMPARE_EQ (typ, 0, 6, "string"))
-	{
-	  int len;
-	  if (extract_keyword (is, "length", len) && len >= 0)
-	    {
-	      OCTAVE_LOCAL_BUFFER (char, tmp, len+1);
-
-	      if (len > 0 && ! is.read (X_CAST (char *, tmp), len))
-		{
-		  error ("load: failed to load string constant");
-		}
-	      else
-		{
-		  tmp [len] = '\0';
-
-		  if (is)
-		    tc = tmp;
-		  else
-		    error ("load: failed to load string constant");
-		}
-	    }
-	  else
-	    error ("load: failed to extract string length");
-	}
-      else if (SUBSTRING_COMPARE_EQ (typ, 0, 5, "range"))
-	{
-	  // # base, limit, range comment added by save ().
-
-	  skip_comments (is);
-	  Range tmp;
-	  is >> tmp;
-	  if (is)
-	    tc = tmp;
-	  else
-	    error ("load: failed to load range constant");
-	}
-      else
-	error ("load: unknown constant type `%s'", tag.c_str ());
+      tc.load_ascii (is);
     }
   else
     error ("load: failed to extract keyword specifying value type");
@@ -679,186 +426,12 @@
 
   octave_value val = val_arg;
 
-  if (val.is_range ())
-    {
-      Range r = val.range_value ();
-      double base = r.base ();
-      double limit = r.limit ();
-      double inc = r.inc ();
-      if (! (NINT (base) == base
-	     && NINT (limit) == limit
-	     && NINT (inc) == inc))
-	val = val.matrix_value ();
-    }	
-
-  if (val.is_string ())
-    {
-      ascii_save_type (os, "string array", mark_as_global);
-      charMatrix chm = val.char_matrix_value ();
-      int elements = chm.rows ();
-      os << "# elements: " << elements << "\n";
-      for (int i = 0; i < elements; i++)
-	{
-	  unsigned len = chm.cols ();
-	  os << "# length: " << len << "\n";
-	  std::string tstr = chm.row_as_string (i, false, true);
-	  const char *tmp = tstr.data ();
-	  if (tstr.length () > len)
-	    panic_impossible ();
-	  os.write (X_CAST (char *, tmp), len);
-	  os << "\n";
-	}
-    }
-  else if (val.is_range ())
-    {
-      ascii_save_type (os, "range", mark_as_global);
-      Range tmp = val.range_value ();
-      os << "# base, limit, increment\n";
-      octave_write_double (os, tmp.base ());
-      os << " ";
-      octave_write_double (os, tmp.limit ());
-      os << " ";
-      octave_write_double (os, tmp.inc ());
-      os << "\n";
-    }
-  else if (val.is_real_scalar ())
-    {
-      ascii_save_type (os, "scalar", mark_as_global);
-
-      double d = val.double_value ();
-
-      if (strip_nan_and_inf)
-	{
-	  if (xisnan (d))
-	    {
-	      error ("only value to plot is NaN");
-	      success = false;
-	    }
-	  else
-	    {
-	      d = xisinf (d) ? (d > 0 ? OCT_RBV : -OCT_RBV) : d;
-	      octave_write_double (os, d);
-	      os << "\n";
-	    }
-	}
-      else
-	{
-	  if (! infnan_warned && (xisnan (d) || xisinf (d)))
-	    {
-	      warning ("save: Inf or NaN values may not be reloadable");
-	      infnan_warned = true;
-	    }
-
-	  octave_write_double (os, d);
-	  os << "\n";
-	}
-    }
-  else if (val.is_real_matrix ())
-    {
-      ascii_save_type (os, "matrix", mark_as_global);
-
-      os << "# rows: " << val.rows () << "\n"
-	 << "# columns: " << val.columns () << "\n";
-
-      Matrix tmp = val.matrix_value ();
+  if (mark_as_global)
+    os << "# type: global " << val.type_name () << "\n";
+  else
+    os << "# type: " << val.type_name() << "\n";
 
-      if (strip_nan_and_inf)
-	tmp = strip_infnan (tmp);
-      else if (! infnan_warned && tmp.any_element_is_inf_or_nan ())
-	{
-	  warning ("save: Inf or NaN values may not be reloadable");
-	  infnan_warned = true;
-	}
-
-      os << tmp;
-    }
-  else if (val.is_cell ())
-    {
-      ascii_save_type (os, "cell", mark_as_global);
-
-      os << "# rows: " << val.rows () << "\n"
-	 << "# columns: " << val.columns () << "\n";
-
-      Cell tmp = val.cell_value ();
-      
-      for (int j = 0; j < tmp.cols (); j++)
-	{
-	  for (int i = 0; i < tmp.rows (); i++)
-	    {
-	      octave_value o_val = tmp.elem (i, j);
-
-	      // Recurse to print sub-value.
-	      bool b = save_ascii_data (os, o_val, CELL_ELT_TAG,
-					infnan_warned, strip_nan_and_inf,
-					mark_as_global, 0);
-
-	      if (! b)
-		return os;
-	    }
-
-	  os << "\n";
-	}
-    }
-  else if (val.is_complex_scalar ())
-    {
-      ascii_save_type (os, "complex scalar", mark_as_global);
-
-      Complex c = val.complex_value ();
-
-      if (strip_nan_and_inf)
-	{
-	  if (xisnan (c))
-	    {
-	      error ("only value to plot is NaN");
-	      success = false;
-	    }
-	  else
-	    {
-	      double re = real (c);
-	      double im = imag (c);
-
-	      re = xisinf (re) ? (re > 0 ? OCT_RBV : -OCT_RBV) : re;
-	      im = xisinf (im) ? (im > 0 ? OCT_RBV : -OCT_RBV) : im;
-
-	      c = Complex (re, im);
-
-	      octave_write_complex (os, c);
-	      os << "\n";
-	    }
-	}
-      else
-	{
-	  if (! infnan_warned && (xisnan (c) || xisinf (c)))
-	    {
-	      warning ("save: Inf or NaN values may not be reloadable");
-	      infnan_warned = true;
-	    }
-
-	  octave_write_complex (os, c);
-	  os << "\n";
-	}
-    }
-  else if (val.is_complex_matrix ())
-    {
-      ascii_save_type (os, "complex matrix", mark_as_global);
-
-      os << "# rows: " << val.rows () << "\n"
-	 << "# columns: " << val.columns () << "\n";
-
-      ComplexMatrix tmp = val.complex_matrix_value ();
-
-      if (strip_nan_and_inf)
-	tmp = strip_infnan (tmp);
-      else if (! infnan_warned && tmp.any_element_is_inf_or_nan ())
-	{
-	  warning ("save: Inf or NaN values may not be reloadable");
-	  infnan_warned = true;
-	}
-
-      os << tmp;
-    }
-  else
-    gripe_wrong_type_arg ("save", val, false);
+  success = val . save_ascii(os, infnan_warned, strip_nan_and_inf);
 
   os.precision (old_precision);