diff liboctave/data-conv.cc @ 4944:44046bbaa52c

[project @ 2004-08-31 05:30:46 by jwe]
author jwe
date Tue, 31 Aug 2004 05:30:47 +0000
parents 6cb22b9e3942
children 25c2664861bc
line wrap: on
line diff
--- a/liboctave/data-conv.cc
+++ b/liboctave/data-conv.cc
@@ -32,6 +32,26 @@
 #include "data-conv.h"
 #include "lo-error.h"
 
+#if defined HAVE_LONG_LONG_INT
+#define FIND_SIZED_INT_TYPE(VAL, BITS, TQ, Q) \
+  do \
+    { \
+      int sz = BITS / CHAR_BIT; \
+      if (sizeof (TQ char) == sz) \
+	VAL = oct_data_conv::dt_ ## Q ## char; \
+      else if (sizeof (TQ short) == sz) \
+	VAL = oct_data_conv::dt_ ## Q ## short; \
+      else if (sizeof (TQ int) == sz) \
+	VAL = oct_data_conv::dt_ ## Q ## int; \
+      else if (sizeof (TQ long) == sz) \
+	VAL = oct_data_conv::dt_ ## Q ## long; \
+      else if (sizeof (TQ long long) == sz) \
+	VAL = oct_data_conv::dt_ ## Q ## longlong; \
+      else \
+        VAL = oct_data_conv::dt_unknown; \
+    } \
+  while (0)
+#else
 #define FIND_SIZED_INT_TYPE(VAL, BITS, TQ, Q) \
   do \
     { \
@@ -48,6 +68,7 @@
         VAL = oct_data_conv::dt_unknown; \
     } \
   while (0)
+#endif
 
 #define FIND_SIZED_FLOAT_TYPE(VAL, BITS) \
   do \
@@ -101,6 +122,52 @@
     }
 }
 
+static std::string
+strip_spaces (const std::string& str)
+{
+  int n = str.length ();
+
+  int k = 0;
+
+  std::string s (n, ' ');
+
+  for (int i = 0; i < n; i++)
+    if (! isspace (str[i]))
+      s[k++] = tolower (str[i]);
+
+  s.resize (k);
+
+  return s;
+}
+
+#define GET_SIZED_INT_TYPE(T, U) \
+  do \
+    { \
+      switch (sizeof (T)) \
+	{ \
+	case 1: \
+	  retval = dt_ ## U ## int8; \
+	  break; \
+ \
+	case 2: \
+	  retval = dt_ ## U ## int16; \
+	  break; \
+ \
+	case 4: \
+	  retval = dt_ ## U ## int32; \
+	  break; \
+ \
+	case 8: \
+	  retval = dt_ ## U ## int64; \
+	  break; \
+ \
+	default: \
+	  retval = dt_unknown; \
+	  break; \
+	} \
+    } \
+  while (0)
+
 oct_data_conv::data_type
 oct_data_conv::string_to_data_type (const std::string& str)
 {
@@ -117,62 +184,57 @@
       initialized = true;
     }
 
-  // XXX FIXME XXX -- finish implementing this.
-
-  int n = str.length ();
-
-  int k = 0;
-
-  std::string s (n, ' ');
+  std::string s = strip_spaces (str);
 
-  for (int i = 0; i < n; i++)
-    if (! isspace (str[i]))
-      s[k++] = tolower (str[i]);
-
-  s.resize (k);
-
-  if (s == "char")
+  if (s == "int8" || s == "integer*1")
+    retval = dt_int8;
+  else if (s == "uint8")
+    retval = dt_uint8;
+  else if (s == "int16" || s == "integer*2")
+    retval = dt_int16;
+  else if (s == "uint16")
+    retval = dt_uint16;
+  else if (s == "int32" || s == "integer*4")
+    retval = dt_int32;
+  else if (s == "uint32")
+    retval = dt_uint32;
+  else if (s == "int64" || s == "integer*8")
+    retval = dt_int64;
+  else if (s == "uint64")
+    retval = dt_uint64;
+  else if (s == "single" || s == "float32" || s == "real*4")
+    retval = dt_single;
+  else if (s == "double" || s == "float64" || s == "real*8")
+    retval = dt_double;
+  else if (s == "char" || s == "char*1")
     retval = dt_char;
   else if (s == "schar" || s == "signedchar")
     retval = dt_schar;
   else if (s == "uchar" || s == "unsignedchar")
     retval = dt_uchar;
   else if (s == "short")
-    retval = dt_short;
+    GET_SIZED_INT_TYPE (short, );
   else if (s == "ushort" || s == "unsignedshort")
-    retval = dt_ushort;
+    GET_SIZED_INT_TYPE (unsigned short, u);
   else if (s == "int")
-    retval = dt_int;
+    GET_SIZED_INT_TYPE (int, );
   else if (s == "uint" || s == "unsignedint")
-    retval = dt_uint;
+    GET_SIZED_INT_TYPE (unsigned int, u);
   else if (s == "long")
-    retval = dt_long;
+    GET_SIZED_INT_TYPE (long, );
   else if (s == "ulong" || s == "unsignedlong")
-    retval = dt_ulong;
+    GET_SIZED_INT_TYPE (unsigned long, u);
+  else if (s == "longlong")
+    GET_SIZED_INT_TYPE (long long, );
+  else if (s == "ulonglong" || s == "unsignedlonglong")
+    GET_SIZED_INT_TYPE (unsigned long long, u);
   else if (s == "float")
-    retval = dt_float;
-  else if (s == "double")
-    retval = dt_double;
-  else if (s == "int8" || s == "char*1" || s == "integer*1")
-    retval = sized_type_table[0][0];
-  else if (s == "int16" || s == "integer*2")
-    retval = sized_type_table[0][1];
-  else if (s == "int32" || s == "integer*4")
-    retval = sized_type_table[0][2];
-  else if (s == "int64" || s == "integer*8")
-    retval = sized_type_table[0][3];
-  else if (s == "uint8")
-    retval = sized_type_table[1][0];
-  else if (s == "uint16")
-    retval = sized_type_table[1][1];
-  else if (s == "uint32")
-    retval = sized_type_table[1][2];
-  else if (s == "uint64")
-    retval = sized_type_table[1][3];
-  else if (s == "float32" || s == "real*4")
-    retval = sized_type_table[2][2];
-  else if (s == "float64" || s == "real*8")
-    retval = sized_type_table[2][3];
+    {
+      if (sizeof (float) == sizeof (double))
+	retval = dt_double;
+      else
+	retval = dt_single;
+    }
   else
     (*current_liboctave_error_handler) ("invalid data type specified");
 
@@ -183,7 +245,217 @@
   return retval;
 }
 
-#define swap_1_bytes(x, y)
+void
+oct_data_conv::string_to_data_type
+  (const std::string& str, int& block_size,
+   oct_data_conv::data_type& input_type,
+   oct_data_conv::data_type& output_type)
+{
+  block_size = 1;
+  input_type = dt_uchar;
+  output_type = dt_double;
+
+  bool input_is_output = false;
+
+  std::string s = strip_spaces (str);
+
+  size_t pos = 0;
+
+  if (s[0] == '*')
+    input_is_output = true;
+  else
+    {
+      size_t len = s.length ();
+
+      while (pos < len && isdigit (s[pos]))
+	pos++;
+
+      if (pos > 0)
+	{
+	  if (s[pos] == '*')
+	    {
+	      block_size = atoi (s.c_str ());
+	      s = s.substr (pos+1);
+	    }
+	  else
+	    {
+	      (*current_liboctave_error_handler)
+		("invalid repeat count in `%s'", str.c_str ());
+
+	      return;
+	    }
+	}
+    }
+
+  pos = s.find ('=');
+
+  if (pos != std::string::npos)
+    {
+      if (s[pos+1] == '>')
+	{
+	  if (input_is_output)
+	    {
+	      input_is_output = false;
+
+	      (*current_liboctave_warning_handler)
+		("warning: ignoring leading * in fread precision");
+	    }
+
+	  input_type = string_to_data_type (s.substr (0, pos));
+	  output_type = string_to_data_type (s.substr (pos+2));
+	}
+      else
+	(*current_liboctave_error_handler)
+	  ("fread: invalid precision specified");
+    }
+  else
+    {
+      input_type = string_to_data_type (s);
+
+      if (input_is_output)
+	output_type = input_type;
+    }
+}
+
+void
+oct_data_conv::string_to_data_type
+  (const std::string& str, int& block_size,
+   oct_data_conv::data_type& output_type)
+{
+  block_size = 1;
+  output_type = dt_double;
+
+  std::string s = strip_spaces (str);
+
+  size_t pos = 0;
+
+  size_t len = s.length ();
+
+  while (pos < len && isdigit (s[pos]))
+    pos++;
+
+  if (pos > 0)
+    {
+      if (s[pos] == '*')
+	{
+	  block_size = atoi (s.c_str ());
+	  s = s.substr (pos+1);
+	}
+      else
+	{
+	  (*current_liboctave_error_handler)
+	    ("invalid repeat count in `%s'", str.c_str ());
+
+	  return;
+	}
+    }
+
+  output_type = string_to_data_type (s);
+}
+
+std::string
+oct_data_conv::data_type_as_string (oct_data_conv::data_type dt)
+{
+  std::string retval;
+
+  switch (dt)
+    {
+    case oct_data_conv::dt_int8:
+      retval = "int8";
+      break;
+
+    case oct_data_conv::dt_uint8:
+      retval = "uint8";
+      break;
+
+    case oct_data_conv::dt_int16:
+      retval = "int16";
+      break;
+
+    case oct_data_conv::dt_uint16:
+      retval = "uint16";
+      break;
+
+    case oct_data_conv::dt_int32:
+      retval = "int32";
+      break;
+
+    case oct_data_conv::dt_uint32:
+      retval = "uint32";
+      break;
+
+    case oct_data_conv::dt_int64:
+      retval = "int64";
+      break;
+
+    case oct_data_conv::dt_uint64:
+      retval = "uint64";
+      break;
+
+    case oct_data_conv::dt_single:
+      retval = "single";
+      break;
+
+    case oct_data_conv::dt_double:
+      retval = "double";
+      break;
+
+    case oct_data_conv::dt_char:
+      retval = "char";
+      break;
+
+    case oct_data_conv::dt_schar:
+      retval = "signed char";
+      break;
+
+    case oct_data_conv::dt_uchar:
+      retval = "usigned char";
+      break;
+
+    case oct_data_conv::dt_short:
+      retval = "short";
+      break;
+
+    case oct_data_conv::dt_ushort:
+      retval = "unsigned short";
+      break;
+
+    case oct_data_conv::dt_int:
+      retval = "int";
+      break;
+
+    case oct_data_conv::dt_uint:
+      retval = "usigned int";
+      break;
+
+    case oct_data_conv::dt_long:
+      retval = "long";
+      break;
+
+    case oct_data_conv::dt_ulong:
+      retval = "usigned long";
+      break;
+
+    case oct_data_conv::dt_longlong:
+      retval = "long long";
+      break;
+
+    case oct_data_conv::dt_ulonglong:
+      retval = "unsigned long long";
+      break;
+
+    case oct_data_conv::dt_float:
+      retval = "float";
+      break;
+
+    case oct_data_conv::dt_unknown:
+    default:
+      retval = "unknown";
+      break;
+    }
+
+  return retval;
+}
 
 #define LS_DO_READ(TYPE, swap, data, size, len, stream) \
   do \
@@ -193,7 +465,7 @@
 	  volatile TYPE *ptr = X_CAST (volatile TYPE *, data); \
 	  stream.read (X_CAST (char *, ptr), size * len); \
 	  if (swap) \
-	    swap_ ## size ## _bytes (ptr, len); \
+	    swap_bytes< size > (ptr, len); \
 	  TYPE tmp = ptr[0]; \
 	  for (int i = len - 1; i > 0; i--) \
 	    data[i] = ptr[i]; \
@@ -247,205 +519,206 @@
 // XXX FIXME XXX -- assumes sizeof (float) == 4
 
 static void
-IEEE_big_double_to_IEEE_little_double (double *d, int len)
+IEEE_big_double_to_IEEE_little_double (void *d, int len)
 {
-  swap_8_bytes (d, len);
+  swap_bytes<8> (d, len);
 }
 
 static void
-VAX_D_double_to_IEEE_little_double (double * /* d */, int /* len */)
+VAX_D_double_to_IEEE_little_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "IEEE little endian format");
 }
 
 static void
-VAX_G_double_to_IEEE_little_double (double * /* d */, int /* len */)
+VAX_G_double_to_IEEE_little_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "IEEE little endian format");
 }
 
 static void
-Cray_to_IEEE_little_double (double * /* d */, int /* len */)
+Cray_to_IEEE_little_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "IEEE little endian format");
 }
 
 static void
-IEEE_big_float_to_IEEE_little_float (float *d, int len)
+IEEE_big_float_to_IEEE_little_float (void *d, int len)
 {
-  swap_4_bytes (d, len);
+  swap_bytes<4> (d, len);
 }
 
 static void
-VAX_D_float_to_IEEE_little_float (float * /* d */, int /* len */)
+VAX_D_float_to_IEEE_little_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "IEEE little endian format");
 }
 
 static void
-VAX_G_float_to_IEEE_little_float (float * /* d */, int /* len */)
+VAX_G_float_to_IEEE_little_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "IEEE little endian format");
 }
 
 static void
-Cray_to_IEEE_little_float (float * /* d */, int /* len */)
+Cray_to_IEEE_little_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "IEEE little endian format");
 }
 
 static void
-IEEE_little_double_to_IEEE_big_double (double *d, int len)
+IEEE_little_double_to_IEEE_big_double (void *d, int len)
 {
-  swap_8_bytes (d, len);
+  swap_bytes<8> (d, len);
 }
 
 static void
-VAX_D_double_to_IEEE_big_double (double * /* d */, int /* len */)
+VAX_D_double_to_IEEE_big_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "IEEE big endian format");
 }
 
 static void
-VAX_G_double_to_IEEE_big_double (double * /* d */, int /* len */)
+VAX_G_double_to_IEEE_big_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "IEEE big endian format");
 }
 
 static void
-Cray_to_IEEE_big_double (double * /* d */, int /* len */)
+Cray_to_IEEE_big_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "IEEE big endian format");
 }
 
 static void
-IEEE_little_float_to_IEEE_big_float (float *d, int len)
+IEEE_little_float_to_IEEE_big_float (void *d, int len)
 {
-  swap_4_bytes (d, len);
+  swap_bytes<4> (d, len);
 }
 
 static void
-VAX_D_float_to_IEEE_big_float (float * /* d */, int /* len */)
+VAX_D_float_to_IEEE_big_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "IEEE big endian format");
 }
 
 static void
-VAX_G_float_to_IEEE_big_float (float * /* d */, int /* len */)
+VAX_G_float_to_IEEE_big_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "IEEE big endian format");
 }
 
 static void
-Cray_to_IEEE_big_float (float * /* d */, int /* len */)
+Cray_to_IEEE_big_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "IEEE big endian format");
 }
 
 static void
-IEEE_little_double_to_VAX_D_double (double * /* d */, int /* len */)
+IEEE_little_double_to_VAX_D_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE little endian", "VAX D");
 }
 
 static void
-IEEE_big_double_to_VAX_D_double (double * /* d */, int /* len */)
+IEEE_big_double_to_VAX_D_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE big endian", "VAX D");
 }
 
 static void
-VAX_G_double_to_VAX_D_double (double * /* d */, int /* len */)
+VAX_G_double_to_VAX_D_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "VAX D");
 }
 
 static void
-Cray_to_VAX_D_double (double * /* d */, int /* len */)
+Cray_to_VAX_D_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "VAX D");
 }
 
 static void
-IEEE_little_float_to_VAX_D_float (float * /* d */, int /* len */)
+IEEE_little_float_to_VAX_D_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE little endian", "VAX D");
 }
 
 static void
-IEEE_big_float_to_VAX_D_float (float * /* d */, int /* len */)
+IEEE_big_float_to_VAX_D_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE big endian", "VAX D");
 }
 
 static void
-VAX_G_float_to_VAX_D_float (float * /* d */, int /* len */)
+VAX_G_float_to_VAX_D_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "VAX D");
 }
 
 static void
-Cray_to_VAX_D_float (float * /* d */, int /* len */)
+Cray_to_VAX_D_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("Cray", "VAX D");
 }
 
 static void
-IEEE_little_double_to_VAX_G_double (double * /* d */, int /* len */)
+IEEE_little_double_to_VAX_G_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE little endian", "VAX G");
 }
 
 static void
-IEEE_big_double_to_VAX_G_double (double * /* d */, int /* len */)
+IEEE_big_double_to_VAX_G_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE big endian", "VAX G");
 }
 
 static void
-VAX_D_double_to_VAX_G_double (double * /* d */, int /* len */)
+VAX_D_double_to_VAX_G_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "VAX G");
 }
 
 static void
-Cray_to_VAX_G_double (double * /* d */, int /* len */)
+Cray_to_VAX_G_double (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "VAX G");
 }
 
 static void
-IEEE_little_float_to_VAX_G_float (float * /* d */, int /* len */)
+IEEE_little_float_to_VAX_G_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE little endian", "VAX G");
 }
 
 static void
-IEEE_big_float_to_VAX_G_float (float * /* d */, int /* len */)
+IEEE_big_float_to_VAX_G_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("IEEE big endian", "VAX G");
 }
 
 static void
-VAX_D_float_to_VAX_G_float (float * /* d */, int /* len */)
+VAX_D_float_to_VAX_G_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX D float", "VAX G");
 }
 
 static void
-Cray_to_VAX_G_float (float * /* d */, int /* len */)
+Cray_to_VAX_G_float (void * /* d */, int /* len */)
 {
   gripe_data_conversion ("VAX G float", "VAX G");
 }
 
 void
-do_double_format_conversion (double *data, int len,
-			     oct_mach_info::float_format fmt)
+do_double_format_conversion (void *data, int len,
+			     oct_mach_info::float_format from_fmt,
+			     oct_mach_info::float_format to_fmt)
 {
-  switch (oct_mach_info::native_float_format ())
+  switch (to_fmt)
     {
     case oct_mach_info::flt_fmt_ieee_little_endian:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  break;
@@ -473,7 +746,7 @@
       break;
 
     case oct_mach_info::flt_fmt_ieee_big_endian:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_double_to_IEEE_big_double (data, len);
@@ -501,7 +774,7 @@
       break;
 
     case oct_mach_info::flt_fmt_vax_d:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_double_to_VAX_D_double (data, len);
@@ -529,7 +802,7 @@
       break;
 
     case oct_mach_info::flt_fmt_vax_g:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_double_to_VAX_G_double (data, len);
@@ -565,13 +838,14 @@
 }
 
 void
-do_float_format_conversion (float *data, int len,
-			    oct_mach_info::float_format fmt)
+do_float_format_conversion (void *data, int len,
+			    oct_mach_info::float_format from_fmt,
+			    oct_mach_info::float_format to_fmt)
 {
-  switch (oct_mach_info::native_float_format ())
+  switch (to_fmt)
     {
     case oct_mach_info::flt_fmt_ieee_little_endian:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  break;
@@ -599,7 +873,7 @@
       break;
 
     case oct_mach_info::flt_fmt_ieee_big_endian:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_float_to_IEEE_big_float (data, len);
@@ -627,7 +901,7 @@
       break;
 
     case oct_mach_info::flt_fmt_vax_d:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_float_to_VAX_D_float (data, len);
@@ -655,7 +929,7 @@
       break;
 
     case oct_mach_info::flt_fmt_vax_g:
-      switch (fmt)
+      switch (from_fmt)
 	{
 	case oct_mach_info::flt_fmt_ieee_little_endian:
 	  IEEE_little_float_to_VAX_G_float (data, len);
@@ -691,8 +965,32 @@
 }
 
 void
+do_float_format_conversion (void *data, size_t sz, int len,
+			    oct_mach_info::float_format from_fmt,
+			    oct_mach_info::float_format to_fmt)
+{
+  switch (sz)
+    {
+    case sizeof (float):
+      do_float_format_conversion (data, len, from_fmt, to_fmt);
+      break;
+
+    case sizeof (double):
+      do_double_format_conversion (data, len, from_fmt, to_fmt);
+      break;
+
+    default:
+      (*current_liboctave_error_handler)
+	("impossible state reached in file `%s' at line %d",
+	 __FILE__, __LINE__);
+      break;
+    }
+}
+
+
+void
 read_doubles (std::istream& is, double *data, save_type type, int len,
-	      int swap, oct_mach_info::float_format fmt)
+	      bool swap, oct_mach_info::float_format fmt)
 {
   switch (type)
     {
@@ -724,7 +1022,7 @@
       {
 	volatile float *ptr = X_CAST (float *, data);
 	is.read (X_CAST (char *, data), 4 * len);
-	do_float_format_conversion (X_CAST (float *, data), len, fmt);
+	do_float_format_conversion (data, len, fmt);
 	float tmp = ptr[0];
 	for (int i = len - 1; i > 0; i--)
 	  data[i] = ptr[i];