changeset 471:32fb3a762074

[project @ 1994-06-06 08:55:13 by jwe]
author jwe
date Mon, 06 Jun 1994 08:55:32 +0000
parents 693d18604ccb
children 33fe06de2c90
files liboctave/dMatrix.cc liboctave/dMatrix.h src/file-io.cc
diffstat 3 files changed, 172 insertions(+), 311 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/dMatrix.cc
+++ b/liboctave/dMatrix.cc
@@ -2223,7 +2223,7 @@
  * Read an array of data froma file in binary format.
  */
 int
-Matrix::read (FILE *fptr, int size, Matrix::conversion conv)
+Matrix::read (FILE *fptr, char *type)
 {
 // Allocate buffer pointers.
 
@@ -2232,7 +2232,6 @@
       void *vd;
       char *ch;
       u_char *uc;
-//    s_char *sc; // Some systems may need this?
       short *sh;
       u_short *us;
       int *in;
@@ -2244,73 +2243,54 @@
     }
   buf;
 
-  buf.db = fortran_vec ();
-
-// Read data directly into matrix data array.
-
-  int count = fread (buf.ch, size, length (), fptr);
-
 // Convert data to double.
 
-  int k;
-
-  switch (conv)
+  if (! type)
     {
-    case CNV_DOUBLE:
-      break;
-
-    case CNV_CHAR:
-      for (k = count - 1; k > -1; k--)
-	buf.db[k] = buf.ch[k];
-      break;
+      (*current_liboctave_error_handler)
+	("fread: invalid NULL type parameter");
+      return 0;
+    }    
 
-    case CNV_UCHAR:
-      for (k = count - 1; k > -1; k--)
-	buf.db[k] = buf.uc[k];
-      break;
+  int count;
+  int nitems = length ();
 
-// Some systems may need this??
-//    case CNV_SCHAR:
-//      for (k = count - 1; k > -1; k--)
-//	buf.db[k] = buf.sc[k];
-//      break;
-
-    case CNV_SHORT:
-      for (k = count - 1; k > -1; k--)
-	buf.db[k] = buf.sh[k];
-      break;
+  double *d = fortran_vec (); // Ensures only one reference to my privates!
 
-    case CNV_USHORT:
-      for (k = count - 1; k > -1; k--)
-	buf.db[k] = buf.us[k];
-      break;
-
-    case CNV_INT:
-      for (k = count - 1; k > -1; k--)
-	buf.db[k] = buf.in[k];
-      break;
-
-    case CNV_UINT:
-      for (k = count - 1; k > -1; k--)
-	buf.db[k] = buf.ui[k];
-      break;
+#define DO_FREAD(TYPE,ELEM) \
+  do \
+    { \
+      size_t size = sizeof (TYPE); \
+      buf.ch = new char [size * nitems]; \
+      count = fread (buf.ch, size, nitems, fptr); \
+      for (int k = 0; k < count; k++) \
+	d[k] = buf.ELEM[k]; \
+      delete [] buf.ch; \
+    } \
+  while (0)
 
-    case CNV_LONG:
-      for (k = count - 1; k > -1; k--)
-	buf.db[k] = buf.ln[k];
-      break;
-
-    case CNV_ULONG:
-      for (k = count - 1; k > -1; k--)
-	buf.db[k] = buf.ul[k];
-      break;
-
-    case CNV_FLOAT:
-      for (k = count - 1; k > -1; k--)
-	buf.db[k] = buf.fl[k];
-      break;
-
-    default:
+  if (strcasecmp (type, "double") == 0)
+    DO_FREAD (double, db);
+  else if (strcasecmp (type, "char") == 0)
+    DO_FREAD (char, ch);
+  else if (strcasecmp (type, "uchar") == 0)
+    DO_FREAD (u_char, uc);
+  else if (strcasecmp (type, "short") == 0)
+    DO_FREAD (short, sh);
+  else if (strcasecmp (type, "ushort") == 0)
+    DO_FREAD (u_short, us);
+  else if (strcasecmp (type, "int") == 0)
+    DO_FREAD (int, in);
+  else if (strcasecmp (type, "uint") == 0)
+    DO_FREAD (u_int, ui);
+  else if (strcasecmp (type, "long") == 0)
+    DO_FREAD (long, ul);
+  else if (strcasecmp (type, "float") == 0)
+    DO_FREAD (float, fl);
+  else
+    {
+      (*current_liboctave_error_handler)
+	("fread: invalid NULL type parameter");
       return 0;
     }
 
@@ -2321,7 +2301,7 @@
  * Write the data array to a file in binary format.
  */
 int
-Matrix::write (FILE *fptr, int size, Matrix::conversion conv)
+Matrix::write (FILE *fptr, char *type)
 {
 // Allocate buffer pointers.
 
@@ -2330,7 +2310,6 @@
       void *vd;
       char *ch;
       u_char *uc;
-//    s_char *sc; // Some systems may need this?
       short *sh;
       u_short *us;
       int *in;
@@ -2342,84 +2321,60 @@
     }
   buf;
 
-  int len = length ();
+  int nitems = length ();
 
-  if (conv != CNV_DOUBLE)
-    buf.db = new double [len];
-
-  double *bufi = fortran_vec ();
+  double *d = fortran_vec ();
 
 // Convert from double to correct size.
 
-  int k;
-
-  switch (conv)
+  if (! type)
     {
-    case CNV_DOUBLE:
-      buf.db = bufi;
-      break;
+      (*current_liboctave_error_handler)
+	("fwrite: invalid NULL type parameter");
+      return 0;
+    }    
 
-    case CNV_CHAR:
-      for (k = 0; k < len; k++)
-	buf.ch[k] = (char) bufi[k];
-      break;
+  size_t size;
+  int count;
 
-    case CNV_UCHAR:
-      for (k = 0; k < len; k++)
-	buf.uc[k] = (u_char) bufi[k];
-      break;
-
-// Some systems may need this?
-//    case CNV_SCHAR:
-//      for (k = 0; k < len; k++)
-//	buf.uc[k] = (s_char) bufi[k];
-//      break;
-
-    case CNV_SHORT:
-      for (k = 0; k < len; k++)
-	buf.sh[k] = (short) bufi[k];
-      break;
-
-    case CNV_USHORT:
-      for (k = 0; k < len; k++)
-	buf.us[k] = (u_short) bufi[k];
-      break;
+#define DO_FWRITE(TYPE,ELEM) \
+  do \
+    { \
+      size = sizeof (TYPE); \
+      buf.ELEM = new TYPE [nitems]; \
+      for (int k = 0; k < nitems; k++) \
+	buf.ELEM[k] = (TYPE) d[k]; \
+      count = fwrite (buf.ELEM, size, nitems, fptr); \
+      delete [] buf.ELEM; \
+    } \
+  while (0)
 
-    case CNV_INT:
-      for (k = 0; k < len; k++)
-	buf.in[k] = (int) bufi[k];
-      break;
-
-    case CNV_UINT:
-      for (k = 0; k < len; k++)
-	buf.ui[k] = (u_int) bufi[k];
-      break;
-
-    case CNV_LONG:
-      for (k = 0; k < len; k++)
-	buf.ln[k] = (long) bufi[k];
-      break;
-
-    case CNV_ULONG:
-      for (k = 0; k < len; k++)
-	buf.ul[k] = (u_long) bufi[k];
-      break;
-
-    case CNV_FLOAT:
-      for (k = 0; k < len; k++)
-	buf.fl[k] = (float) bufi[k];
-      break;
-
-    default:
+  if (strcasecmp (type, "double") == 0)
+    DO_FWRITE (double, db);
+  else if (strcasecmp (type, "char") == 0)
+    DO_FWRITE (char, ch);
+  else if (strcasecmp (type, "uchar") == 0)
+    DO_FWRITE (u_char, uc);
+  else if (strcasecmp (type, "short") == 0)
+    DO_FWRITE (short, sh);
+  else if (strcasecmp (type, "ushort") == 0)
+    DO_FWRITE (u_short, us);
+  else if (strcasecmp (type, "int") == 0)
+    DO_FWRITE (int, in);
+  else if (strcasecmp (type, "uint") == 0)
+    DO_FWRITE (u_int, ui);
+  else if (strcasecmp (type, "long") == 0)
+    DO_FWRITE (long, ln);
+  else if (strcasecmp (type, "ulong") == 0)
+    DO_FWRITE (u_long, ul);
+  else if (strcasecmp (type, "float") == 0)
+    DO_FWRITE (float, fl);
+  else
+    {
+      (*current_liboctave_error_handler)
+	("fwrite: unrecognized type parameter %s", type);
       return 0;
-  }
-
-// Write data from converted matrix data array.
-
-  int count = fwrite (buf.ch, size, length (), fptr);
-
-  if (conv != CNV_DOUBLE)
-    delete [] buf.db;
+    }
 
   return count;
 }
--- a/liboctave/dMatrix.h
+++ b/liboctave/dMatrix.h
@@ -227,25 +227,8 @@
   friend ostream& operator << (ostream& os, const Matrix& a);
   friend istream& operator >> (istream& is, Matrix& a);
 
-  enum conversion
-    {
-      CNV_UNKNOWN,
-      CNV_UCHAR,
-      CNV_CHAR,
-      CNV_SCHAR,
-      CNV_SHORT,
-      CNV_USHORT,
-      CNV_INT,
-      CNV_UINT,
-      CNV_LONG,
-      CNV_ULONG,
-      CNV_FLOAT,
-      CNV_DOUBLE,
-    };
-
-
-  int read (FILE *fptr, int size, Matrix::conversion);
-  int write (FILE *fptr, int size, Matrix::conversion);
+  int read (FILE *fptr, char *type);
+  int write (FILE *fptr, char *type);
 
 // Until templates really work with g++:
 
--- a/src/file-io.cc
+++ b/src/file-io.cc
@@ -1208,114 +1208,46 @@
 }
 
 /*
- * Find out how many elements are left.
- *
- *   size is the size of the elements
- *   nr is the number of rows or columns in the matrix
+ * Find out how many elements are left to read.
  */
 static long
-get_whats_left (FILE *fptr, int size, int nn)
+num_items_remaining (FILE *fptr, char *type)
 {
+  size_t size;
+
+  if (strcasecmp (type, "uchar") == 0)
+    size = sizeof (u_char);
+  else if (strcasecmp (type, "char") == 0)
+    size = sizeof (char);
+  else if (strcasecmp (type, "short") == 0)
+    size = sizeof (short);
+  else if (strcasecmp (type, "ushort") == 0)
+    size = sizeof (u_short);
+  else if (strcasecmp (type, "int") == 0)
+    size = sizeof (int);
+  else if (strcasecmp (type, "uint") == 0)
+    size = sizeof (u_int);
+  else if (strcasecmp (type, "long") == 0)
+    size = sizeof (long);
+  else if (strcasecmp (type, "ulong") == 0)
+    size = sizeof (u_long);
+  else if (strcasecmp (type, "float") == 0)
+    size = sizeof (float);
+  else if (strcasecmp (type, "double") == 0)
+    size = sizeof (double);
+  else
+    return 0;
+
   long curr_pos = ftell (fptr);
 
   fseek (fptr, 0, SEEK_END);
   long end_of_file = ftell (fptr);
 
-  fseek (fptr, end_of_file, SEEK_SET);
+  fseek (fptr, curr_pos, SEEK_SET);
 
   long len = end_of_file - curr_pos;
 
-  long num_items = len / size / nn;
-
-  if (len > num_items * size * nn)
-    num_items++;
-
-  return num_items;
-}
-
-static void
-get_size_conv (const char *preci, int& size, Matrix::conversion& conv,
-	       const char *warn)
-{
-// Get type and number of bytes per element to read.
-
-  char *prec = strdup (preci);
-  char *ip = prec;
-
-  while (*ip > 0)
-    {
-      tolower (*ip);
-      ip++;
-    }
-
-  if (strcmp (prec, "uchar") == 0)
-    {
-      size = 1;
-      conv = Matrix::CNV_UCHAR;
-    }
-  else if (strcmp (prec, "char") == 0)
-    {
-      size = 1;
-      conv = Matrix::CNV_CHAR;
-    }
-  else if (strcmp (prec, "schar") == 0)
-    {
-      size = 1;
-      conv = Matrix::CNV_CHAR;
-// Some systems may need this??
-// size = 1;
-// conv = CNV_SCHAR;
-    }
-  else if (strcmp (prec, "short") == 0)
-    {
-      size = 2;
-      conv = Matrix::CNV_SHORT;
-    }
-  else if (strcmp (prec, "ushort") == 0)
-    {
-      size = 2;
-      conv = Matrix::CNV_USHORT;
-    }
-  else if (strcmp (prec, "int") == 0)
-    {
-      size = 4;
-      conv = Matrix::CNV_INT;
-    }
-  else if (strcmp (prec, "uint") == 0)
-    {
-      size = 4;
-      conv = Matrix::CNV_UINT;
-    }
-  else if (strcmp (prec, "long") == 0)
-    {
-      size = 4;
-      conv = Matrix::CNV_LONG;
-    }
-  else if (strcmp (prec, "ulong") == 0)
-    {
-      size = 4;
-      conv = Matrix::CNV_ULONG;
-    }
-  else if (strcmp (prec, "float") == 0)
-    {
-      size = 4;
-      conv = Matrix::CNV_FLOAT;
-    }
-  else if (strcmp (prec, "double") == 0)
-    {
-      size = 8;
-      conv = Matrix::CNV_DOUBLE;
-    }
-  else
-    {
-      error ("%s: precision: \'%s\' unknown", warn, prec);
-      size = -1;
-      conv = Matrix::CNV_UNKNOWN;
-    }
-
-  delete [] prec;
-
-  return;
+  return len / size;
 }
 
 /*
@@ -1364,86 +1296,87 @@
 	}
     }
 
-  int size;
-  Matrix::conversion conv;
-  get_size_conv (prec, size, conv, "fread");
-  if (size < 0)
-    return retval;
+// Get file info.
 
-// Get file info.
   file_info file = file_list (p);
-  FILE * fptr = file.fptr ();
+
+  FILE *fptr = file.fptr ();
 
 // Set up matrix to read into.  If specified in arguments use that
 // number, otherwise read everyting left in file.
 
-  double dnr = 1.0;
-  double dnc = 1.0;
-  int nr = 1;
-  int nc = 1;
+  double dnr = 0.0;
+  double dnc = 0.0;
+  int nr;
+  int nc;
 
   if (nargin > 2)
     {
-// tree_constant tmpa = args[2].make_numeric (); // ??
-
       if (args[2].is_scalar_type ())
 	{
 	  tree_constant tmpa = args[2].make_numeric ();
-
-	  dnr = 1.0;
-	  dnc = tmpa.double_value ();
+	  dnr = tmpa.double_value ();
+	  dnc = 1.0;
 	}
       else if (args[2].is_matrix_type ())
 	{
-// tree_constant tmpa = args[2].make_numeric (); // ??
-      Matrix tmpm = args[2].to_matrix ();
-      nr = tmpm.rows ();
-      nc = tmpm.columns ();
+	  ColumnVector tmp = args[2].to_vector ();
 
-      if(nr != 1 || nc > 2)
+	  if (tmp.length () == 2)
+	    {
+	      dnr = tmp.elem (0);
+	      dnc = tmp.elem (1);
+	    }
+	  else
+	    {
+	      error ("fread: invalid size specification\n");
+	      return retval;
+	    }
+	}
+
+      if ((xisinf (dnr)) && (xisinf (dnc)))
 	{
-	  error ("fread: Illegal size specification\n");
-	  print_usage ("fread");
+	  error ("fread: number of rows and columns cannot both be infinite");
 	  return retval;
 	}
-      dnr = tmpm.elem (0, 0);
-      dnc = tmpm.elem (0, 1);
-    }
 
-    if ((xisinf (dnr)) && (xisinf (dnc)))
-      {
-	error ("fread: number of rows and columns cannot both be infinite\n");
-	return retval;
-      }
-
-    if (xisinf (dnr))
-      {
-	nc = NINT (dnc);
-	nr = get_whats_left (fptr, size, nc);
-      }
-    else if (xisinf (dnc))
-      {
-	nr = NINT (dnr);
-	nc = get_whats_left (fptr, size, nr);
-      }
-    else
-      {
-	nr = NINT (dnr);
-	nc = NINT (dnc);
-      }
+      if (xisinf (dnr))
+	{
+	  nc = NINT (dnc);
+	  int n = num_items_remaining (fptr, prec);
+	  nr = n / nc;
+	  if (n > nr * nc)
+	    nr++;
+	}
+      else if (xisinf (dnc))
+	{
+	  nr = NINT (dnr);
+	  int n = num_items_remaining (fptr, prec);
+	  nc = n / nr;
+	  if (n > nc * nr)
+	    nc++;
+	}
+      else
+	{
+	  nr = NINT (dnr);
+	  nc = NINT (dnc);
+	}
     }
   else
     {
 // No size parameter, read what's left of the file.
-      nr = 1;
-      nc = get_whats_left (fptr, size, nr);
+      nc = 1;
+      int n = num_items_remaining (fptr, prec);
+      nr = n / nc;
+      if (n > nr * nc)
+	nr++;
     }
 
   Matrix m (nr, nc, octave_NaN);
 
 // Read data.
 
-  int count = m.read (fptr, size, conv);
+  int count = m.read (fptr, prec);
 
   if (nargout > 1)
     {
@@ -1497,21 +1430,11 @@
 	}
     }
 
-  int size;
-  Matrix::conversion conv;
-  get_size_conv(prec, size, conv, "fwrite");
-  if (size < 0)
-    return retval;
-
-// Get file info.
   file_info file = file_list (p);
 
-// Write the matrix data.
-  tree_constant tmpa = args[2].make_numeric ();
+  Matrix m = args[2].to_matrix ();
 
-  Matrix tmpm = tmpa.to_matrix ();
-
-  int count = tmpm.write (file.fptr(), size, conv);
+  int count = m.write (file.fptr (), prec);
 
   retval = new tree_constant[2];
   retval[0] = tree_constant ((double) count);